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