我正在尝试学习x86程序集。我正在使用的书是Assembly Language - Step by Step, Programming With Linux
(我必须说它非常好)。到目前为止我学到了很多,但我觉得我也应该挑战自己,在很多方面保持领先,这样我就可以通过做更快的学习(我可以跟随,自上而下的学习,但我发现它很乏味慢)。
所以,我认为尝试将两个寄存器(32位)相乘然后将数据输出到控制台是一个很酷的主意。
问题在于,当我执行程序时(我正在使用NASM,就像本书一样 - 虽然没有Insight调试器),但是我收到了一个分段错误。我已经在 gdb 中完成了相当多的调试,但是无论出于何种原因,我似乎无法弄清楚问题是什么。
我想知道为什么我会收到分段错误,这是一个多么好的方法 谴责这个问题。另外,如果我在代码中提出的评论与目前的评论不符,我将不胜感激,如果有人能够纠正我的话。
到目前为止,这是我的代码(评论很好)
感谢。
teh codez
section .data
;TODO
section .bss
valueToPrint: resb 4 ;alloc 4 bytes of data in 'valueToPrint'
section .text
global _start
_mul:
mov eax, 0x2A ;store 42 in eax
mov edx, 0x2A ;store 42 in edx
mul eax
ret
_safe_exit:
mov eax, 1 ;initiate 'exit' syscall
mov ebx, 0 ;exit with error code 0
int 0x80 ;invoke kernel to do its bidding
_start:
nop ;used to keep gdb from complaining
call _mul ;multiply the values
mov [valueToPrint], eax ;store address of eax in the contents of valueToPrint
mov eax, 4 ;specify a system write call - aka syswrite
mov ebx, 1 ;direction used to make the syswrite call output to console - i.e. stdout
mov dword [ecx], valueToPrint ;store valueToPrint in ecx: ecx represents the syswrite register
int 0x80 ;invoke kernel based on the given parameters
call _safe_exit
修改
此外,我正在运行Arch Linux,如果这有所不同。
答案 0 :(得分:3)
此行导致分段错误:
mov dword [ecx], valueToPrint
您告诉它将valueToPrint
存储在地址ecx
的内存位置。你永远不会初始化ecx
(内核可能在程序启动时将它初始化为0),所以当你取消引用它时,你将访问一个无效的内存位置。
write(2)
系统调用需要3个参数:寄存器ebx
中的文件描述符编号,指向要写入ecx
的字符串的指针,以及要写入的字节数{ {1}}。因此,如果您只想打印结果的原始二进制数据,您可以传递edx
的地址,并告诉它从该地址打印4个字节。在这种情况下,valueToPrint
为1764(十六进制为0x6e4),因此此代码将在x86上打印出4个字节valueToPrint
,这是小端:
e4 06 00 00
答案 1 :(得分:1)
EDITIT! (忘了一个cmp!)
以基数10输出值...
; assuming value is in EAX (only)
.loop1:
div 10 ; divide by 10, leave result in eax, REMAINDER in edx
push eax ; save value
mov eax,edx
or eax,0x30 ; convert 0-9 to '0'-'9' (ascii 0x30='0')
call display_a_char ; (you write this!)
pop eax
or eax,eax ; set flags (edit!)
jnz .loop1
; all done, maybe put a \n return or something here