在 AT&T 汇编中从 ascii 转换为整数
Posted
技术标签:
【中文标题】在 AT&T 汇编中从 ascii 转换为整数【英文标题】:Convert from ascii to integer in AT&T Assembly 【发布时间】:2015-08-16 10:45:07 【问题描述】:如何从 ascii 转换为整数?
data
asd:
.int 32
.text
.globl _start
_start:
movl $4, %eax
movl $1, %ebx
movl $1,(asd)
add $48,(asd)
movl $asd, %ecx
movl $4, %edx
int $0x80
# Exit the program
movl $1, %eax
movl $0, %ebx
int $0x80
代码正在写一个ascii值,我想如果我可以将48加到值上。我可以写,但我不能打印,一个两阶段的数字“例如 53 或 156”。如何打印?
【问题讨论】:
你必须一次做一个数字。除以 10 以隔离下一个数字。 NASM 版本:NASM Assembly convert input to integer? 【参考方案1】:通常最好先考虑高级语言版本。如果数字有n
数字并且存储在数组a
中,那么我们想要:
char *p = a;
unsigned val = 0;
while (n > 0)
n--;
val = 10 * val + (*p++ - '0');
假设%esi
是p
以上%eax
是val
,而%ecx
是n
。
逐行翻译以使其尽可能简单和字面意思:
movl $n, %ecx
movl $a, %esi
xorl %eax, %eax # val = 0
eval_while_cond:
testl %ecx, %ecx # if (n <= 0)
jle done # goto done
subl $1, %ecx # n--
movl %eax, %ebx # tmp1 = val
imul $10, %ebx # tmp1 = 10 * tmp1
movzbl (%esi), %eax # tmp2 = *p
addl $1, %esi # p++
subl $'0, %eax # tmp2 = tmp2 - '0'
addl %eax, %ebx # val = tmp2 + tmp1
jmp eval_while_cond
done:
# result is now in %eax
请注意,这只是获取函数式汇编语言的一般方法。这没有以任何方式优化。获得最佳性能所需的技巧是另一个主题。
其他选项是使用编译器(例如https://godbolt.org/z/WzGYjePzx),使用 -O1、-Og 或 -Os 等轻度优化来获得一些可读的 asm(尽管在这种情况下,它们使用了不完全明显的技巧LEA 乘以 10 并减去 '0'
(48
),否则它们会弄乱奇怪的循环条件。)另见 How to remove "noise" from GCC/clang assembly output?
【讨论】:
mul
不适用于立即数,你需要imul
,AT&T 语法中的注释字符是#
。另外,更喜欢test %ecx, %ecx
instead of or
。有关此循环的有效版本,请参阅 NASM Assembly convert input to integer?。 (除非它在 *p
不是数字时停止,而不是使用计数循环。)以上是关于在 AT&T 汇编中从 ascii 转换为整数的主要内容,如果未能解决你的问题,请参考以下文章
x86 汇编 (AT&T):如何在运行时为变量动态分配内存?