x86-64汇编:命令行参数转整数存入变量失败问题排查
命令行参数存储与字符串转整数问题分析与解决
问题原因
- 存储参数后
x/s查看乱码:你将命令行参数的内存地址存入了port变量,但调试时直接用x/s 0x403024是把port变量自身的字节当作字符串解析。port里存的是64位地址值,不是ASCII字符序列,自然显示乱码。正确操作应该是把port里的内容当作地址,再读取对应内存的字符串。 sub rax, '0'得到空字符串:rax里是字符串的内存地址,不是单个字符的ASCII值。直接对地址做减法会得到无效内存地址,读取该地址内容自然为空或乱码。字符串转整数需要逐个处理每个字符,而非对地址操作。
解决方法
一、正确存储命令行参数地址并验证
x86_64 Linux程序启动后,栈布局为:argc → argv[0](程序名地址)→ argv[1](第一个参数地址)→ ... → NULL。若已通过pop rax拿到参数"8080"的地址:
- 执行
mov [port], rax将地址存入变量,这一步本身是正确的。 - 调试查看参数内容时,需用GDB命令
x/s *(char**)0x403024——该命令会先取出port变量里的地址值,再读取对应地址的字符串。
二、正确将字符串参数转为整数存入port
需要逐个遍历字符串的每个字符,转为数字后累加计算。示例汇编代码(nasm语法,x86_64 Linux):
section .data port dq 0 ; 定义64位变量存储最终整数 section .text global _start _start: ; 从栈中取出第一个命令行参数地址 pop rdi ; rdi = argc pop rsi ; rsi = argv[0](程序名) pop rsi ; rsi = argv[1](目标参数地址) xor rdx, rdx ; 初始化结果寄存器为0 convert_loop: mov bl, [rsi] ; 读取当前字符到bl test bl, bl ; 判断是否到达字符串结束符 jz convert_done sub bl, '0' ; 将ASCII字符转为数字(0-9) imul rdx, 10 ; 结果乘以10,为新数字腾出位置 add rdx, rbx ; 加上当前数字(rbx是bl的零扩展) inc rsi ; 指针移动到下一个字符 jmp convert_loop convert_done: mov [port], rdx ; 将最终整数存入port变量 ; 程序退出逻辑 mov rax, 60 xor rdi, rdi syscall
调试验证
- 执行到
convert_done时,rdx寄存器的值为十进制8080(十六进制0x1f90) - 用GDB命令
x/q 0x403024查看port变量,会显示0x0000000000001f90,对应十进制8080
内容的提问来源于stack exchange,提问作者Charlie Benger-Stevenson
相关产品推荐
相关产品推荐

