问题描述
我需要制作一个C ++程序来分配可以加减1024和2048位二进制数的赋值,并且执行上述操作的函数必须在Assembly中进行。我尝试通过将数字解释为32位二进制数的64位长数组,然后从末尾开始将它们依次添加一个元素,然后将结果写入第三个数组来解决这个问题。但是,在为每个仅具有3个32位数字的数组制作了测试版本之后,我面临着该函数不响应的事实。我试图制作一个可以使用预定数据的函数版本,但FASM编译器说“错误:保留字用作符号”。在任何地方都找不到答案,所以现在我在这里寻求帮助。
module.exports = {
name: "ping",description: "Basic ping command",execute(message) {
message.channel.send("Pong.").then((botMessage) => {
botMessage.react("?");
});
},};
文件本身中该行的错误消息(编辑者注:来自我的计算机,而不是OP):
section '.data' data readable writable
IN_NUM1 dd 0b00000100000000000000000000000000,0b00000100000000000000000000000000,0b00000111111111111111111111111111 ;"error: reserved word used as symbol" is here
IN_NUM2 dd 0b00000010000000000000000000000000,0b00000010000000000000000000000000,0b00000100000000000000000000000000
OUT_NUM dd 0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000000000000
section '.code' code readable writable executable
start:
mov edi,[IN_NUM1]
mov esi,[IN_NUM2]
mov ecx,3
PUSHING:
mov eax,[edi]
push eax
mov eax,[esi]
push eax
inc edi
inc esi
loop PUSHING
clc
ADDING:
pop eax
pop ebx
adc eax,ebx
mov [OUT_NUM+ecx-1],eax
loop ADDING
ccall [printf],[OUT_NUM]
ccall [getchar]
stdcall [ExitProcess],0
但是flat assembler version 1.73.24 (16384 kilobytes memory,x64)
foo.asm [1]:
IN_NUM1 dd 0b00000100000000000000000000000000,0b00000111111111111111111111111111 ;"error: reserved word used as symbol" is here
processed: IN_NUM1 dd 0b00000100000000000000000000000000,0b00000111111111111111111111111111
error: reserved word used as symbol.
组装得很好。
作者的编辑: 感谢@PeterCordes的帮助,我取得了良好的进展。但是,仍然存在一些问题。使用新代码,加法如下所示:87654321 + 00000000,FFFFFFFF + 00000001、04000000 +02000000。如果我不将ecx乘以4,它将变为“ 00000012 + 00000087、00001234 + 00008765、00123456 + 00876543”。我不知道为什么会发生这种情况,非常感谢您的帮助。至于代码本身:
IN_NUM1 dd 1,2,4
解决方法
无需在源代码中使用2底,您可以像普通人一样以十六进制形式编写它们。写入相同数字的任何方式都会在汇编器输出中转换为相同的二进制位模式。另外,您可以在C ++中定义数组及其内容,并将指针传递给asm函数。
请参阅FASM手册的1.2.4 Numerical expressions部分(通过在手册中搜索“二进制”一词可以找到它):
默认情况下,表达式中的数字被视为十进制,二进制数字应在末尾附加
b
字母,八进制数字应以o
字母结尾,十六进制数字应以0x
字符(如C语言)或$
字符(如Pascal语言)开头,或者应以h
字母结尾。在表达式中遇到的带引号的字符串也将转换为数字-第一个字符将成为数字的最低有效字节。
所以它是like NASM,但仅支持 101b
,
不是以2为底的NASM的101y
或0b101
等。
顺便说一句,处理FASM无用的错误消息的第一步是尝试使用不同的数字语法,以确保组装IN_NUM1 dd 1,2,4
之类的东西。既然如此,那表明写数字的语法不是FASM想要的,而是语法的其他部分。
顺便说一句,您无需按下并弹出您的输入。存储您的数据为低位字节序(最低有效块在前),或者如果您确实需要,则向后循环。通过使用lea
,可以增加指针或索引而不影响FLAGS。或inc
/ dec
保留CF不变。 (较旧的Intel CPU(P6系列)将在inc
/ adc
循环中有performance problems,但Skylake has no flag-merging cost at all中有{}。
您可以inc
朝零递增一个负索引,并且相对于数组的末端索引,因此循环逻辑可以为inc ecx
/ jnz
。如果您不打算展开循环,这对于性能来说是相当不错的,尽管adc reg,[reg + ecx*4]
甚至在Skylake上也不会微熔断(由于索引寻址模式,un-laminate会在问题/重命名时出现)。