【问题标题】:NASM Code In Linux Gives Me Segmentation FaultLinux 中的 NASM 代码给了我分段错误
【发布时间】:2011-06-26 05:04:37
【问题描述】:

我开始学习如何使用 NASM 汇编编程语言编写程序。我编写了这个简单的程序,提示用户输入两个数字,然后将两个操作数相加。我让它编译没有错误或警告,但是当它提示用户输入两个数字并开始添加这两个数字时,它会打印出分段错误并且程序结束。我知道分段错误相当于 Win32 世界中的访问读/写冲突异常。但是,因为我不知道如何调试 NASM 代码;我不知道出了什么问题。我怀疑它与无效指针有关;但我不知道。下面是代码:

section .data 
    msg1: db 'Please Enter A Number: ', 0
    length1: equ $ - msg1
    msg2: db 'Please Enter A Second Number: ', 0
    length2: equ $ - msg2

section .bss
    operand1: resb 255
    operand2: resb 255
    answer: resb 255
section .text
    global _start

_start:

    ; Print first message

    mov eax, 4
    mov ebx, 1
    mov ecx, msg1
    mov edx, length1
    int 80h

    ; Now read value

    mov eax, 3
    mov ebx, 1
    mov ecx, operand1
    mov edx, 255
    int 80h

    ; Print second message

    mov eax, 4
    mov ebx, 1
    mov ecx, msg2
    mov edx, length2
    int 80h

    ; Now read second value

    mov eax, 3
    mov ebx, 1
    mov ecx, operand2
    mov edx, 255
    int 80h

    ; Now add operand1 and operand2 and print answer

    mov eax, 4
    mov ebx, 1
    xor ecx, ecx ; Make the ecx register 0
    mov ecx, operand1
    add ecx, operand2
    mov edx, 510
    int 80h

【问题讨论】:

  • 在 gdb 中运行你的代码,看看它在哪条指令上崩溃
  • 如何使用 gdb 调试我的代码?抱歉,Linux 新手。

标签: linux ubuntu segmentation-fault nasm


【解决方案1】:

(除此之外:你应该从STDIN_FILENO = 0 阅读,而不是STDOUT_FILENO = 1。另外,你正在写一个NUL 字符,你不应该。)

问题在于operand1operand2 是存储您已读取字符的内存位置的地址。当你添加它们时,你会得到一个指向无效内存的指针。

您必须先将它们转换为整数,添加它们,然后再转换回字符串,然后才能将其写出。

【讨论】:

  • 或者,换句话说,取消引用指针。您当前正在将指针相加,而不是它们指向的数字。
  • @Scott:他们不指向数字;至少按照现在的设计,它们指向字符串。
  • 那么如何将字符串转换为整数,然后再转换回字符串。我知道它在 C 中的算法,但我对如何在 NASM 中做到这一点有点困惑。
  • @Daniel:你知道如何用 C 编写它很好。这样做,应该很容易将它逐行翻译成汇编。如果你真的卡住了,你可以编译你的 C 代码然后反汇编它,但是编译器生成的程序集并不总是那么简单。
【解决方案2】:

ecx 中的值是调用 int 80h 时要打印的字符串地址。最后一部分没有意义

mov eax, 4
mov ebx, 1
xor ecx, ecx ; Make the ecx register 0
mov ecx, operand1
add ecx, operand2 ; **<<< invalid memory address now in ECX !!!**
mov edx, 510
int 80h

因为您要添加字符串操作数 1 的地址和字符串操作数 2 的地址,并尝试打印最有可能指向无处的结果地址。

要使用 gdb 调试程序,您可以:

nasm -f elf64 -g -l q1.lst q1.asm gcc -o q1 q1.o

我用“main”替换了“_start”,这样gcc就不会抱怨了,如果你是在32位平台上构建的,你可以跳过“-f elf64”中的64。

gdb q1

这是一个 gdb 会话示例:

(gdb) br 主要 0x4004d0 处的断点 1:文件 q1.asm,第 20 行。 (gdb) r 启动程序:/home/anonymous/Projects/asm/q1

Breakpoint 1, main () at q1.asm:20
20      mov eax, 4
(gdb) n
21      mov ebx, 1
(gdb) n
22      mov ecx, msg1
(gdb) n
23      mov edx, length1
(gdb) p msg1
$1 = 1634036816
(gdb) 

【讨论】:

  • 我已经解决了。问题是我没有取消引用,也没有将其转换为整数并返回其字符串表示形式。
猜你喜欢
  • 2012-05-09
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 2013-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多