[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を使うことができることをよく承知していますが、うまくいくでしょうが、ここで何が起こっているのかを実際に理解しようとしています。32ビットモードでNASM x86_64アセンブリ:なぜこの命令はRIP相対アドレッシングコードを生成するのですか?
私は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
代わりに、私はそれが期待するように、そのアドレスの値をロードすると、このラインを使用する場合は、アセンブラ出力はRIP相対アドレッシング、GDBに示すようにデバッガと私は単になぜ思っています。
mov 0x6000e5(%rip),%edx # 0xa001a5
は今、私の代わりにEAXレジスタを使用してみました(その後、EDXにEAXを移動する)、その後私は別の問題を取得しました。私は、GDBに述べたように、セグメンテーションフォールトを取得し終わる:
movabs 0x4b8c289006000e5,%eax
はそう明らかに、別のレジスタが異なるコードを生成します。どういうわけか上位32ビットを切り捨てる必要があると思いますが、その方法はわかりません。
str_hello_lengthのアドレスでeaxをロードしてから、eaxが指すアドレスの内容を読み込み、すべてが大変です。
mov eax, str_hello_length
mov edx, [eax] ; count
; gdb disassembly
mov $0x6000e5,%eax
mov (%rax),%edx
明らかにmemアドレスから値を間接的にロードしようとすると、異なるコードが生成されますか?私は本当に知らない。
私はこれらの命令の構文と操作を理解する上で助けが必要なので、有効なアドレスをロードする方法の理由をよく理解できます。うん、私はちょうどEQUに切り替えて私の気持ちがいいと思うけど、DB宣言とそのアドレスから読み込んでいることを理解するまで続けることができないと思う。
これは32ビットモードではありません。 'rip'と' rax'は32ビットモードでは存在しません。ですから問題は、実際には64ビットコードを持つ32ビット用のコードを生成していると考えていることです。つまり、角括弧で明示的に 'rip'を指定しなくても、相対メモリアドレスを作成することはx86_64のデフォルトです。 – hirschhornsalz
それは私が組み立ててリンクする方法かもしれません。私は持っている:アセンブルのためのnasm -g -f elf64 $ <とリンクするためのld -o $(PROJECT_NAME)$(OBJ)。 lf:i386の入力ファイル 'main.o 'のアーキテクチャがi386と互換性がない:x86-64出力 – Mathmagician
リンクに' gcc -m32'を使うか、適切なldフラグ( ' -m elf_i386')。 – mirabilos