在 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');

假设%esip 以上%eaxval,而%ecxn。 逐行翻译以使其尽可能简单和字面意思:

  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, %ecxinstead of or。有关此循环的有效版本,请参阅 NASM Assembly convert input to integer?。 (除非它在 ​​*p 不是数字时停止,而不是使用计数循环。)

以上是关于在 AT&T 汇编中从 ascii 转换为整数的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 AT&T 汇编代码会出现分段错误?

英特尔 AT&T 汇编程序的逐步执行?

将 AT&T 语法程序转换为 intel 语法

x86 汇编 (AT&T):如何在运行时为变量动态分配内存?

有没有一种简单的方法可以在 AT&T 汇编中像这样将两个寄存器相乘:%eax * %ebx = %ecx

AT&T汇编语言及其寻址方式