0

我正在阅读这个汇编教程并且我得到了这个例子,所以我决定尝试改进它。一旦我这样做了,它就停止工作了,所以我尝试将它转换为 AT&T 语法,这样我就可以用 gcc 编译它并获取调试信息(因为我在 OS X 上,而 nasm 不会为 Mach 生成调试信息- O 格式)。

我试图转换可以工作的原始程序,但在我使用 AT&T 语法编写后它停止工作。我使用 gdb 调试它,发现%rsp我希望包含 argc 的 包含 value 0x93b2e5ad。intel 语法版本没有发生这种情况。

所以我的问题是,为什么%rsp在 AT&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

我像这样编译了英特尔版本:

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
4

0 回答 0