1

我在 64 位 lubuntu 中对 nasm 进行堆栈实现时遇到问题。在其他 ubuntu 操作系统中,它可以正常工作和运行,当我在在线编译器上运行它时,它也可以正常运行。我一直在考虑我的操作系统是否不支持 nasm 上的堆栈,或者只是需要应用一些代码。

section .data   
    num dw 0
    x dw 5
    y dw 4
    newline db "",10
    newlineLen equ $-newline

section .bss

section .text
    global _start

_start:
    sub esp,2
        push word[x]
    push word[y]
    call sum
    pop word[num] ;fetch the sum from the stack

    ;convert num for printing
    add word[num],30h

    mov eax,4
    mov ebx,1
    mov ecx,num
    mov edx,1
    int 80h

    mov eax,4
    mov ebx,1
    mov ecx,newline
    mov edx,newlineLen
    int 80h

    mov eax,1
    mov ebx,0
    int 80h

sum:

    mov ebp,esp
    mov ax,[ebp+6] ;5
    add ax,[ebp+4] ;4+5
    mov [ebp+8],ax ;store the result in the space allocated for the sum
    ret 4 ;esp+4
4

2 回答 2

0

你为什么用WORDs?除非你有一个旧的 16 位处理器,否则你应该使用 32 位寄存器和参数,因为这是堆栈对齐的。你在学习汇编?请学习正确的方法 -在进入ebp之前保存esp!!!!!!!请改掉使用“幻数”的习惯,改用常量作为参数

你为什么sub esp, 2一开始 这是不需要的。正确结果的更正代码:

%define sys_exit    1
%define sys_write   4
%define stdout      1

section .data   
num dd 0
x dd 5
y dd 4
newline db "",10
newlineLen equ $-newline

section .bss

section .text
    global _start

_start:
    push    dword[x]
    push    dword[y]
    call    sum
    mov     dword[num], eax 

    ;convert num for printing
    add     dword[num],30h

    mov     eax, sys_write
    mov     ebx, stdout
    mov     ecx, num
    mov     edx, 1
    int     80h

    mov     eax, sys_write
    mov     ebx, stdout
    mov     ecx, newline
    mov     edx, newlineLen
    int     80h

    mov     eax, sys_exit
    xor     ebx, ebx
    int     80h 

sum:
    push    ebp                             ; MUST save ebp!!!
    mov     ebp, esp

    mov     eax, [ebp+12] ;5
    add     eax, [ebp+8] ;4+5
    ;~ Standard way to return a value is in eax
    leave                                   ; same as pop ebp - mov esp, ebp
    ret 4 * 2 
于 2013-08-06T02:56:13.680 回答
0

任何 X86 体系结构都肯定支持堆栈操作。这是汇编程序,因此您并没有真正使用任何操作系统功能(除非您调用操作系统例程)。

段违规表明您已读取或写入不允许的内存位置。平台行为的变化与默认内存布局有关。

我也运行 Ubuntu 12.04 64,获得了 SEGV。

我浏览了您的程序并将寄存器重命名为 64 位名称(eax变成raxebp变成rbpesp变成rsp;等等,您在哪里e??制作r??)并且它运行了。

为什么程序发出 0 而不是 9?

这是因为这些行:

mov ax,[ebp+6] ;5
add ax,[ebp+4] ;4+5
mov [ebp+8],ax ;store the result in the space allocated for the sum

更改axrax,它将起作用。

如果您将0x0000000000000005(一个 64 位值)移动到ax(一个 16 位寄存器)中,您最终会得到0x0000(截断的 .. oops)。相反,您需要参考寄存器的全宽,因此rax.

注意:可能有一个指令强制 nasm 进入 32 位或 16 位模式,但我不知道它是什么。

于 2013-08-05T03:38:38.907 回答