为什么在nasm中进行堆栈时会出现分段错误?

时间:2013-08-05 03:15:11

标签: segmentation-fault stack nasm

我在使用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

2 个答案:

答案 0 :(得分:0)

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

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

我,也在运行Ubuntu 12.04 64,获得一个SEGV。

我浏览了你的程序并将寄存器重命名为64位名称(eax变为rax; ebp变为rbp; esp变为{ {1}};等等,您rsp使其成为e??)然后运行。

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

由于这些原因:

r??

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 更改为ax,它会有效。

如果将rax(64位值)移动到0x0000000000000005(16位寄存器),最后会使用ax(截断的... oops)。相反,您需要引用寄存器的整个宽度,即0x0000

note :可能有一条指令要求将nasm强制为32位或16位模式,但我不知道它是什么。

答案 1 :(得分:0)

为什么使用WORD?除非你有一个旧的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