[bits 32]
global _start
section .data
str_hello db "HelloWorld", 0xa
str_hello_length db $-str_hello
section .text
_start:
mov ebx, 1 ; stdout file descriptor
mov ecx, str_hello ; pointer to string of characters that will be displayed
mov edx, [str_hello_length] ; count outputs Relative addressing
mov eax, 4 ; sys_write
int 0x80 ; linux kernel system call
mov ebx, 0 ; exit status zero
mov eax, 1 ; sys_exit
int 0x80 ; linux kernel system call
ここでの基本的なことは、Linuxのsys_writeシステムコールに渡すためにhello文字列の長さが必要であるということです。今、私はEQUを使用するだけで問題なく動作することをよく知っていますが、ここで何が起こっているのかを本当に理解しようとしています。
したがって、基本的にEQUを使用すると、値が読み込まれ、問題ありません。
str_hello_length equ $-str_hello
...
...
mov edx, str_hello_length
ただし、この行をDBで使用すると
str_hello_length db $-str_hello
...
...
mov edx, [str_hello_length] ; of course, without the brackets it'll load the address, which I don't want. I want the value stored at that address
私が期待するようにそのアドレスに値をロードする代わりに、アセンブラーはgdbデバッガーに示されているようにRIP-Relative Addressingを出力しますが、なぜだろうと思っています。
mov 0x6000e5(%rip),%edx # 0xa001a5
代わりにeaxレジスタを使用してみました(そしてeaxをedxに移動しました)が、別の問題が発生します。gdbに記載されているように、セグメンテーション違反が発生します。
movabs 0x4b8c289006000e5,%eax
明らかに、異なるレジスタは異なるコードを生成します。どういうわけか上位32ビットを切り捨てる必要があると思いますが、その方法がわかりません。
「解決策」を見つけたのですが、次のようになります。eaxにstr_hello_lengthのアドレスをロードしてから、eaxが指すアドレスの内容をロードすると、すべてが厄介です。
mov eax, str_hello_length
mov edx, [eax] ; count
; gdb disassembly
mov $0x6000e5,%eax
mov (%rax),%edx
どうやらmemアドレスから間接的に値をロードしようとすると、異なるコードが生成されますか?よくわかりません。
これらの命令の構文と操作を理解するのに助けが必要なだけなので、効果的なアドレスをロードする方法をよりよく理解できます。ええ、私はEQUに切り替えて陽気な道を進むことができたと思いますが、DB宣言とそのアドレスからのロードで何が起こっているのかを理解するまで、私は本当に先に進むことができないと感じています。