我刚刚学习汇编语言编码。
问:将表示任何有符号整数的字符串转换为其 2 的补码值,结果以小端顺序存储在内存的连续位置。
例如 - 1 = 0xFFFFFFFFFFFFFFFE假设 2 的补码代码是 64 位的。我已经在我的代码中完成了数字 -149,这应该会导致 0xffff ffff ffff ff6b
.data
S: .string "-149"
Result: .quad
.text
.globl main
main:
mov S,%rax
cmp %rax,0
jl positive
sub %rax,%rax
not S
add S,%rax
sub $30,%rax
not %rax
add $1, %rax
mov %rax,Result
positive:
sub $30,%rax
not %rax
add $1,%rax
mov %rax,Result
在 GDB 中,存储的字符串整数的值为 this。
(gdb) x/24xb &S
0x601038: 0x2d 0x31 0x34 0x39 0x00 0x00 0x00 0x00
0x601040: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x601048: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
如果我想对 -149 进行任何计算,我必须以某种方式访问内存中的这些位置 - 我该如何做到这一点?
如果我知道 4 在 10 的位置,我可以将其乘以 10 得到 40,然后将 9 和类似的 1x100 相加得到 100 并添加它。
如何访问它们进行计算?
如何访问它们进行计算?
字符串作为连续字符存储在内存中。 如果是 ASCII(不是 UTF-8),则每个字符都是一个字节。
因此,您可以使用字节加载/存储一次访问一个,例如movzbl 2(%rsi), %eax
获取第 3 个字符(如果rsi
指向字符串的开头)。
或者,如果%rdi
指向最后一个字符(十进制数中的字符),则imul $10, -1(%rdi), %ecx
将%cl
设置为倒数第二个字符加上其位值。 (和%ecx
的上字节到垃圾;最好先做一个movzx
加载,然后再做一个乘法。 不过,这确实可以使低 8 位正确)。
在复杂性范围的另一端,请查看此SSE4.1 IPv4点分四字符串到32位整数转换器。 具体来说,随机播放之后的小数位值部分,使用pmaddubsw
(_mm_maddubs_epi16
)和向量[ ..., 100, 10, 1 ]
来应用位值和一步的水平加法,然后phaddw
水平添加每个虚线四边形中最多三位数字。
还有如何使用 SIMD 实现 atoi?
另请参阅 x86 标签 wiki 以获取许多其他链接。
好吧,我希望这甚至不会编译(例如cmp %rax,0
AT&T语法中不是有效的组合,这看起来像你想要英特尔语法)。
还有一些事情没有任何意义,比如not S
......你认为这会有什么作用?如果你把它注释为字节ptr,它会反转"<"字符(实际上为什么你在S字符串中有"<"和">"也让我感到困惑)。
等等等等...
所以先尝试编译它,然后在调试器中打开它,逐条指令一步一步地步进,并继续查看 CPU 寄存器和内存和指令参考指南......直到它有意义...可能需要一些时间,但实际上不会那么长,也许几天,你会掌握它。