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

如何用NASM汇编实现从首字符开始显示预设字符串的隔位字符

NASM实现每隔一个字符输出预设字符串

下面给出几种Linux环境下的NASM汇编实现,核心逻辑和你提供的C代码完全对应:初始化索引、循环判断索引范围、处理对应字符、索引加2。

方式1:逐个字符输出(x86_64架构)

这种方式直接逐个输出符合条件的字符,逻辑直观,适合新手理解:

section .data
    str     db      'helloworld'   ; 预设的输入字符串
    len     equ     $ - str        ; 自动计算字符串长度,修改字符串后无需手动更新

section .text
    global _start

_start:
    mov     rsi, 0                 ; 初始化索引index=0,用rsi寄存器存储索引
loop_start:
    cmp     rsi, len               ; 比较索引与字符串长度,对应C里的index < len
    jge     loop_end               ; 如果index >= len,跳转到循环结束

    ; 调用Linux sys_write系统输出当前字符
    mov     rax, 1                 ; x86_64下sys_write的系统调用号是1
    mov     rdi, 1                 ; 文件描述符1代表标准输出(stdout)
    lea     rsi, [str + rsi]       ; 获取当前索引对应的字符地址:str[index]
    mov     rdx, 1                 ; 输出长度为1个字节(单个字符)
    syscall                        ; 触发系统调用

    add     rsi, 2                 ; 索引加2,对应C里的index +=2
    jmp     loop_start             ; 回到循环开头继续判断

loop_end:
    ; 调用sys_exit退出程序
    mov     rax, 60                ; x86_64下sys_exit的系统调用号是60
    mov     rdi, 0                 ; 退出码0表示正常退出
    syscall

代码解释:

  • section .data:存放预设的字符串和长度,$ - str是NASM的表达式,$代表当前行的地址,减去字符串起始地址就是字符串的字节长度。
  • _start:Linux ELF程序的入口点,程序从这里开始执行。
  • 循环部分完全对应你提供的C代码逻辑:初始化索引→判断索引是否越界→输出字符→索引加2→循环。

方式2:先构建结果缓冲区再一次性输出(x86_64架构)

这种方式先把需要输出的字符存入缓冲区,再一次性输出,减少系统调用次数,效率更高:

section .data
    str     db      'helloworld'
    len     equ     $ - str
    buf     times len db 0         ; 定义结果缓冲区,长度与原字符串一致

section .text
    global _start

_start:
    mov     rsi, 0                 ; rsi作为原字符串的索引,初始为0
    mov     rdi, 0                 ; rdi作为结果缓冲区的索引,初始为0
loop_start:
    cmp     rsi, len
    jge     print_result           ; 索引越界则跳转到输出结果

    ; 将原字符串当前索引的字符复制到结果缓冲区
    mov     al, [str + rsi]
    mov     [buf + rdi], al

    add     rsi, 2                 ; 原字符串索引加2
    inc     rdi                    ; 结果缓冲区索引加1
    jmp     loop_start

print_result:
    ; 一次性输出结果缓冲区
    mov     rax, 1
    mov     rdi, 1
    mov     rsi, buf
    mov     rdx, rdi               ; rdi的值就是结果的长度
    syscall

    ; 退出程序
    mov     rax, 60
    mov     rdi, 0
    syscall

32位Linux版本示例

如果你的环境是32位Linux,系统调用的寄存器使用和调用号有所不同,代码如下:

section .data
    str     db      'helloworld'
    len     equ     $ - str

section .text
    global _start

_start:
    mov     esi, 0
loop_start:
    cmp     esi, len
    jge     loop_end

    ; 32位下sys_write的调用号是4,用int 0x80触发系统调用
    mov     eax, 4
    mov     ebx, 1
    lea     ecx, [str + esi]
    mov     edx, 1
    int     0x80

    add     esi, 2
    jmp     loop_start

loop_end:
    ; 32位下sys_exit的调用号是1
    mov     eax, 1
    mov     ebx, 0
    int     0x80

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:50:29