このアセンブリ チュートリアルを読んでいて、サンプルが機能するようになったので、改善を試みることにしました。一度実行すると動作しなくなったので、gcc でコンパイルしてデバッグ情報を取得できるように、AT&T 構文に変換しようとしました (OS X を使用していて、nasm は Mach のデバッグ情報を生成しないため)。 O 形式)。
動作する元のプログラムを変換しようとしましたが、AT&T 構文を使用して記述した後、動作しなくなりました。gdb を使用してデバッグしたところ、%rspargc が含まれていると予想していた に値 が含まれていることがわかりました0x93b2e5ad。これは、Intel 構文バージョンでは発生しませんでした。
私の質問は、%rspAT&T バージョンでは argc の値が正しくないのに、Intel バージョンでは正しくないのはなぜですか?
これは元の Intel 構文バージョンです (チュートリアルのバージョンを少し変更しました)。
section .data
WRONG_ARGC db "Must be two command line argument", 0xa
WRONG_ARGC_SIZE equ 34
section .text
global start
start:
pop rcx
cmp rcx, 3
jne argcError
add rsp, 8
pop rsi
call str_to_int
mov r10, rax
pop rsi
call str_to_int
mov r11, rax
add r10, r11
mov rax, r10
xor r12, r12
jmp int_to_str
argcError:
mov rax, 0x2000004
mov rdi, 1
mov rsi, WRONG_ARGC
mov rdx, WRONG_ARGC_SIZE
syscall
jmp exit
; set rdi to exit status before calling
exit:
mov rax, 0x2000001
syscall
str_to_int:
xor rax, rax
mov rcx, 10
next:
cmp [rsi], byte 0
je return_str
mov bl, [rsi]
sub bl, 48
mul rcx
add rax, rbx
inc rsi
jmp next
return_str:
ret
int_to_str:
mov rdx, 0
mov rbx, 10
div rbx
add rdx, 48
; push rdx
dec rsp
mov rsp, rdx
inc r12
cmp rax, 0
jne int_to_str
jmp print
print:
; mov rax, 1
; mul r12
mov rax, r12
; mov r12, 8
; mul r12
mov rdx, rax
mov rax, 0x2000004
mov rdi, 1
mov rsi, rsp
syscall
mov rdi, 0
jmp exit
AT&T 構文に変換した後のコードは次のとおりです。
.data
WRONG_ARGC: .ascii "Must be two command line argument\n"
WRONG_ARGC_SIZE: .quad 34
.text
.globl _main
_main:
popq %rcx
cmpq $3, %rcx
jne argcError
addq $8, %rsp
popq %rsi
call str_to_int
movq %rax, %r10
popq %rsi
call str_to_int
movq %rax, %r11
addq %r11, %r10
movq %r10, %rax
xorq %r12, %r12
jmp int_to_str
argcError:
movq $0x2000004, %rax
movq $1, %rdi
movq WRONG_ARGC@GOTPCREL(%rsi), %rsi
movq WRONG_ARGC_SIZE@GOTPCREL(%rsi), %rdx
syscall
jmp exit
# set rdi to exit status before calling
exit:
movq $0x2000001, %rax
syscall
str_to_int:
xorq %rax, %rax
movq $10, %rcx
next:
cmpq $0, (%rsi)
je return_str
movb (%rsi), %bl
subb $48, %bl
mulq %rcx
addq %rbx, %rax
incq %rsi
jmp next
return_str:
ret
int_to_str:
movq $0, %rdx
movq $10, %rbx
divq %rbx
addq $48, %rdx
push %rdx
#decq %rsp
#movq %rdx, %rsp
incq %r12
cmpq $0, %rax
jne int_to_str
jmp print
print:
movq $1, %rax
mulq %r12
movq %r12, %rax
movq $8, %r12
mulq %r12
movq %rax, %rdx
movq $0x2000004, %rax
movq $1, %rdi
movq %rsp, %rsi
syscall
movq $0, %rdi
jmp exit
次のように Intel バージョンをコンパイルしました。
nasm -f macho64 -o add_intel.o add_intel.s
ld -o add_intel add_intel.s
そして、AT&T バージョンを次のようにコンパイルしました。
gcc -o add_att add_att.s -g