0

我正在开发一个能够在数组中找到最大元素的程序。出于某种原因,当我尝试将矩阵上的第一个元素移动到 ecx 寄存器中以进行输出(只是测试它)时,我遇到了分段错误。

可以肯定的是,我已经尝试了所有不同类型的寻址模式,但我无法弄清楚为什么我会遇到这个错误并且没有任何工作。

这是我的代码:

segment .data

    NUM_ROWS: equ 5
    NUM_COLUMNS: equ 5
    NUM_ROW_BYTES: equ 10

    ;Default matrix
    matrix: dd  5, 4, 9, 7, 2, 1, 4, 6, 8, 7
            ;9, 9, 2, 3, 7
            ;6, 5, 8, 3, 4
            ;1, 2, 8, 2, 6  
    matrixLen: equ $-matrix

    sum:    db "The sum of the last column is: ", 10

    ;FOR TESTING
    works: db 'Works!', 10
    worksLen: equ $-works

segment .bss
    counter resb 1

segment .text
    global main

main:
    mov eax, 4      ; system call 4
    mov ebx, 1      ; standard output 
    mov ecx, [matrix + 4]   
    mov edx, 4
    int 0x80
4

1 回答 1

0

我正在查看我发现的这个 Linux 系统调用列表,似乎没有任何只打印一个字符的调用。您无法使用 sys_write(),但如果您将 EDX 设置为 1 并传递一个有效指针,它可以打印一个字符。

认识到mov ecx, [matrix + 4]仅将 (matrix+4) 指向的值移动到 ECX 中,以便 sys_write 将其用作地址。由于该地址包含 4,因此 sys_write 尝试打印从地址 0x00000004 开始找到的字符串数据。这就是它出现段错误的原因(不允许从那里读取)。

要将值 4 转换为适合打印的 ASCII 值,请将 0x30 添加到该值。ASCII 0x30 = '0',0x31 = '1' ... 0x34 = '4' ... 0x39 = '9'。

因此,打印单个数字的策略是将该数字加载到 ECX 中,添加 0x30,推入您在.bss段中保留的字节(也许digit_to_ascii resb 1),然后digit_to_ascii在调用 sys_write 之前将地址移动到 ECX 中(并且只设置 EDX为 1,因为您只想打印 1 个字节)。

了解这仅适用于打印 1 位数字。如果要打印 10 或更高的数字,则需要按除法拆分每个数字并单独打印(或将其单独写入保留缓冲区并使用一次 sys_write 调用打印整个缓冲区)。

于 2013-03-20T00:15:42.083 回答