【问题标题】:Assembly 'Segmentation Fault' When Trying to Print Decimal Number尝试打印十进制数时的程序集“分段错误”
【发布时间】:2018-09-10 10:18:39
【问题描述】:

我正在尝试创建一个将为我打印十进制数字的宏。我的想法是将数字除以 10,将余数转换为 ASCII 并将其推入堆栈,直到比率为 0。然后我一个接一个地打印数字,但由于某种原因,我得到一个“分段错误”。

我使用的是 Linux、nasm 和 x86_64 处理器。

%macro printInt 1
    mov rax, %1
    mov rbx, 0
%%loop1:                  ;Convert all digits to ascii
    inc rbx               ;Count of the digits in number
    mov rdx, 0
    div rax
    add rdx, 48           ;Convert remainder to ascii
    push rdx              ;Push remainder into stack
    cmp rax, 0            ;Compare ratio to 0
    jne %%loop1
%%loop2:                  ;Print the number digit by digit
    dec rbx

    mov rax, 1            ;Sys_Write
    mov rdi, 1            ;STDOUT
    pop rsi               ;Pop digit
    mov rdx, 1
    syscall

    cmp rbx, 0
    jne %%loop2
%endmacro

section .data
    number1 db 123

section .text
    global _start
_start:

    printInt number1

    mov rax, 60
    mov rdi, 0
    syscall

任何帮助表示赞赏,在此先感谢!

【问题讨论】:

  • idownvotedbecau.se/nodebugging (这是提示“使用调试器”来弄清楚,段错误的原因是什么)......第二个提示是:为什么是宏?我看不出有什么理由把它写成宏而不是标准的子例程(但我有很多理由不把它写成宏,这样使用的宏会使调试和代码审查变得更加困难)
  • 我不知道如何使用 gdu 调试器,我使用了一个宏,因为我猜它让我想起了函数。你能为我推荐一个好的调试器吗?由于某种原因,我似乎无法安装 DDD 或 Insight
  • 我个人使用github.com/eteran/edb-debugger(从源代码编译,但我认为最近一些发行版可能已经在存储库中,尝试搜索“edb-debugger”)。它正在不断发展,到目前为止我不建议将其用于大型项目的调试,但仅用于学习 x86 汇编的基础知识,它应该可以很好地工作,它具有所有基本工具。宏不是函数,宏在您使用它的任何地方都会复制指令。使用适当的功能,即在某处编写代码一次,然后从其他代码中call
  • 在学习 x86 汇编的基础知识时,你应该零需要/使用宏,毕竟这些是汇编指令,而不是使它成为最终二进制文件的东西,所以你可以用宏编写的所有东西,你也可以用纯汇编编写,一开始所有可能闻起来像“宏可以在这里为我节省很多打字”的东西实际上意味着“我应该更好地重组我的汇编”。有时宏可以极大地帮助保持源代码更易于阅读/维护或提高性能,但在您学习基础知识时,这些都不应该出现。

标签: linux assembly x86 nasm x86-64


【解决方案1】:

第一个错误:

number1 db 123

number1 被定义为 BYTE,但将被视为 QUADWORD (mov rax, %1)。改成

number1 dq 123

第二个错误:

printInt number1

宏将参数作为字符串获取。所以,mov rax, %1 将被解析为mov rax, number1。在 NASM 中,RAX 将获得number1 的地址,而不是值。改成

printInt [number1]

第三个错误:

div rax

意思是:将RDX:RAX除以RAX,结果存入RAX,余数存入RDX。这将始终导致 RAX=1 和 RDX=0。使用另一个值为 10 的寄存器。

第四个错误:

pop rsi

内核的 SYSCALL/RAX=1 例程需要 RSI 中的指针,而不是数字。有几种方法可以解决这个问题。我把它留给你想象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 2013-09-23
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    相关资源
    最近更新 更多