如何用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
相关产品推荐
相关产品推荐

