1

I'm trying to learn x86 assembly. The book I'm using is Assembly Language - Step by Step, Programming With Linux (and I'd have to say it's pretty good). I've learned a lot so far, but I feel as though I should also be challenging myself to stay ahead in many respects so I can learn faster through doing (I can do follow along, top-down learning, but I find it tediously slow).

So, I figured it would be a cool idea to try and multiply two registers (32-bit) and then output the data to the console.

The problem is that when I execute the program (I'm using NASM, just as the book does - no Insight debugger though), I receive a segmentation fault. I've done a fair amount of debugging in gdb with this little hammer out, but for whatever reason I can't seem to figure out what the issue is.

I'd like to know why I'm receiving a segmentation fault, and what a good way would be to reprimand the issue. Also, if the comments I've made in the code don't match up with what exactly is happening, I'd be grateful if anyone could correct me on that.

Here's my code so far (it's well commented)

Thanks.

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

Edit

Also, I'm running Arch Linux, if that makes a difference.

4

2 回答 2

3

此行导致分段错误:

mov dword [ecx], valueToPrint

你告诉它存储valueToPrint在 address 的内存位置ecx。您永远不会初始化ecx(内核可能会在程序启动时为您将其初始化为 0),因此当您取消引用它时,您将访问一个无效的内存位置。

系统调用采用write(2)3 个参数:寄存器中的文件描述符编号ebx、指向要写入的字符串的指针以及要写入ecx的字节数edx。因此,如果您只想打印结果的原始二进制数据,您可以传递 的地址valueToPrint,并告诉它从该地址打印 4 个字节。在本例中,valueToPrint是 1764(十六进制中的 0x6e4),因此这段代码将打印出e4 06 00 00x86 上的 4 个字节,即 little-endian:

mov [valueToPrint], eax   ; store the result into memory
mov eax, 4                ; system call #4 = sys_write
mov ebx, 1                ; file descriptor 1 = stdout
mov ecx, valueToPrint     ; store *address* of valueToPrint into ecx
mov edx, 4                ; write out 4 bytes of data
int 0x80                  ; syscall
于 2012-06-29T05:10:39.763 回答
1

编辑!(忘记了一个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
于 2012-06-29T05:32:49.963 回答