You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NASM 64位汇编使用jg指令跳转触发SEGFAULT问题排查

错误原因

你的jg指令逻辑本身是对的:cmp rdi, 0时rdi=1满足大于条件,确实会跳转到greater标签。代码跑崩是三个汇编入门常见的逻辑错误,和跳转指令无关:

  • 分支执行完没有流程控制,CPU直接跑飞。你把greater标签放在了正常退出流程的后面,跳过去之后只执行了写内存的指令,既没有跳回打印/退出逻辑,也没有单独加退出指令,CPU执行完这几句就会顺着地址跑到后面的.bss数据段,把预留的数据空间当指令执行,直接触发段错误。你注释掉jg能跑,本质是程序顺序走完「写内容→打印→退出」的流程后,根本碰不到greater后面的冗余代码。
  • 系统调用参数传错了。x86_64 Linux的write调用要求rdx存要打印的字符串长度数值,你写mov rdx, msg_len传进去的是msg_len这个标签对应的内存地址,根本不是存在里面的长度值,正确写法是mov rdx, [msg_len]。另外你给msg_len只分配了1字节空间(resb 1),但rdx是8字节寄存器,往这个地址写值会越界覆盖后面的内存。
  • 非跳转分支没做初始化。你原来的代码里,不满足跳转条件的分支直接调用write,根本没给msg和msg_len赋值,打出来的只会是.bss段默认的零值,不可能是预期文本。
修正后的可运行代码
BITS 64

section .text
    global _start
_start:
    mov rdi, 1
    cmp rdi, 0
    jg greater

    ; 小于等于分支:写入对应文本
    mov rax, "Less!!!"
    mov [msg], rax
    mov byte [msg_len], 7
    jmp print_and_exit

greater:
    ; 大于分支:写入对应文本
    mov rax, "More!!!"
    mov [msg], rax
    mov byte [msg_len], 7

print_and_exit:
    mov rax, 1          ; write系统调用号
    mov rdi, 1          ; 标准输出文件描述符
    mov rsi, msg        ; 字符串首地址
    mov rdx, [msg_len]  ; 传入长度值,不是地址
    syscall

    mov rax, 60         ; exit系统调用号
    mov rdi, 0
    syscall

section .bss
msg: resb 8            ; 预留8字节存7字符的字符串足够
msg_len: resb 1
容易混淆的概念点

汇编里的标签只是地址标记,不会自动分隔代码块:只要CPU的执行指针走到标签对应的地址,不管是不是跳转目标,都会顺着往后执行指令。所以写完分支逻辑后,一定要用跳转指令把流程导到公共逻辑或者退出点,绝对不能让CPU顺着地址跑到非代码段。另外要严格区分地址和地址里存的值:直接写标签名取到的是地址,加方括号[]才是访问该地址内存里存储的内容。

内容的提问来源于stack exchange,提问作者Lakshay Rohila

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 03:12:24