【问题标题】:What is the difference between dword and 'the stack' in assembler汇编程序中的 dword 和“堆栈”有什么区别
【发布时间】:2013-11-02 16:53:01
【问题描述】:

我正在尝试学习汇编程序,但对 osx 使用 nasm macho32 将参数传递给函数的方法感到有些困惑。

我正在关注 Jeff Duntemann 的“Assembly Language Step By Step”一书,并广泛使用互联网对其进行了修改,使其可以在 32 位和 64 位的 osx 上运行。

所以从书中的 linux 版本开始

section .data           ; Section containing initialised data
    EatMsg db "Eat at Joe's!",10
    EatLen equ $-EatMsg 
section .bss            ; Section containing uninitialised data
section .text           ; Section containing code
global start            ; Linker needs this to find the entry point!

start:
    nop
    mov eax, 4          ; Specify sys_write syscall
    mov ebx, 1          ; Specify File Descriptor 1: Standard Output
    mov ecx, EatMsg     ; Pass offset of the message
    mov edx, EatLen     ; Pass the length of the message
    int 0x80                ; Make syscall to output the text to stdout

    mov eax, 1          ; Specify Exit syscall
    mov ebx, 0          ; Return a code of zero
    int 0x80                ; Make syscall to terminate the program

    section .data       ; Section containing initialised data
        EatMsg db "Eat at Joe's!", 0x0a
        EatLen equ $-EatMsg 
    section .bss        ; Section containing uninitialised data
    section .text       ; Section containing code
    global start        ; Linker needs this to find the entry point!

然后非常类似 osx 的 64 位版本,除了更改寄存器名称,替换 int 80H(我理解这有点过时)并将 0x2000000 添加到移动到 eax 的值(一点都不理解)没什么可改变的。

section .data           ; Section containing initialised data
    EatMsg db "Eat at Joe's!", 0x0a
    EatLen equ $-EatMsg 
section .bss            ; Section containing uninitialised data
section .text           ; Section containing code
global start            ; Linker needs this to find the entry point!

start:
    mov rax, 0x2000004  ; Specify sys_write syscall
    mov rdi, 1          ; Specify File Descriptor 1: Standard Output
    mov rsi, EatMsg     ; Pass offset of the message
    mov rdx, EatLen     ; Pass the length of the message
    syscall             ; Make syscall to output the text to stdout

    mov rax, 0x2000001  ; Specify Exit syscall
    mov rdi, 0          ; Return a code of zero
    syscall             ; Make syscall to terminate the program

另一方面,32 位 mac 版本则完全不同。我可以看到我们正在将参数推送到堆栈 dword,所以我的问题是(对于长序言感到抱歉)eax 被推送到的堆栈和 dword 之间有什么区别,为什么我们只使用寄存器而不是64位版本(和linux)的堆栈?

   section .data        ; Section containing initialised data
    EatMsg db "Eat at Joe's!", 0x0a
    EatLen equ $-EatMsg 
section .bss            ; Section containing uninitialised data
section .text           ; Section containing code
global start            ; Linker needs this to find the entry point!

start:
    mov eax, 0x4        ; Specify sys_write syscall
    push dword EatLen   ; Pass the length of the message
    push dword EatMsg   ; Pass offset of the message
    push dword 1        ; Specify File Descriptor 1: Standard Output
    push eax
    int 0x80            ; Make syscall to output the text to stdout
    add esp, 16         ; Move back the stack pointer

    mov eax, 0x1        ; Specify Exit syscall
    push dword 0        ; Return a code of zero
    push eax
    int 0x80            ; Make syscall to terminate the program

【问题讨论】:

    标签: macos assembly nasm


    【解决方案1】:

    嗯,你不太明白dword 是什么。说HLL,它不是一个变量,而是一个类型。所以push doword 1 意味着你将一个双字常量1 压入堆栈。只有一个栈,栈和寄存器eax都被压入其中。

    在 linux 中使用寄存器是因为它们的速度要快得多,尤其是在旧处理器上。 Linux ABI(据我所知,它是 System V ABI 的后裔)是很久以前开发的,并且经常用于性能至关重要且差异非常显着的系统中。 OSX intel abi 更年轻,更容易使用堆栈,这在桌面 OSX 中比可忽略的减速更重要。在 64 位处理器中,添加的寄存器更多,因此使用它们的效率更高。

    【讨论】:

      猜你喜欢
      • 2016-01-19
      • 1970-01-01
      • 1970-01-01
      • 2016-08-18
      • 2021-05-10
      • 2020-10-24
      • 2013-12-11
      • 2019-01-26
      • 2015-01-15
      相关资源
      最近更新 更多