I need to make a C++ program for an assignment that can add or subtract 1024 and 2048 bit binary numbers, and the functions that do said operations must be made in Assembly. I tried going about this by interpreting the numbers as 64-long arrays of 32 bit binary numbers and adding them one element after another, starting from the end, and writing the result into the third array. However, after making a testing version made for arrays with only 3 32 bit numbers each, I'm faced with the fact that the function doesn't respond. I tried making a version of said function that works predetermined data, but the FASM compiler says "error: reserved word used as symbol.". There isn't an answer I could find anywhere, so now I'm asking for help here.
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
The error message from that line in a file by itself (editor's note: from my computer, not the OP's):
flat assembler version 1.73.24 (16384 kilobytes memory, x64) foo.asm : IN_NUM1 dd 0b00000100000000000000000000000000, 0b00000100000000000000000000000000, 0b00000111111111111111111111111111 ;"error: reserved word used as symbol" is here processed: IN_NUM1 dd 0b00000100000000000000000000000000,0b00000100000000000000000000000000,0b00000111111111111111111111111111 error: reserved word used as symbol.
IN_NUM1 dd 1,2,4 assembles fine.
Author's edit: Thanks to the help of @PeterCordes, I have made good progress. However, there are still some issues. With the new code, the addition goes like this: 87654321 + 00000000, FFFFFFFF + 00000001, 04000000 + 02000000. And if I don't multiply ecx by 4, it goes "00000012 + 00000087, 00001234 + 00008765, 00123456 + 00876543". I don't get why this happens, and I would very much appreciate your help. And as for the code itself:
section '.data' data readable writable IN_NUM1 dd 0x12345678, 0x04000000, 0xFFFFFFFF IN_NUM2 dd 0x87654321, 0x02000000, 0x00000001 OUT_NUM dd 0x00000000, 0x00000000, 0x00000000 section '.code' code readable writable executable start: mov ecx, 3 clc ADDING: mov eax, [IN_NUM1+ecx*4] mov ebx, [IN_NUM2+ecx*4] adc eax, ebx mov [OUT_NUM+ecx*4], eax loop ADDING
There's no need to use base 2 in the source code, you can just write them in hex like a normal person. Any way of writing the same number turns into the same binary bit-pattern in the assembler output. Also, you could define the arrays and their contents in C++, and pass pointers to your asm functions.
See the FASM manual, section 1.2.4 Numerical expressions (which I found by searching on the word "binary" in the manual):
The numbers in the expression are by default treated as a decimal, binary numbers should have the
bletter attached at the end, octal number should end with
oletter, hexadecimal numbers should begin with
0xcharacters (like in C language) or with the
$character (like in Pascal language) or they should end with
hletter. Also quoted string, when encountered in expression, will be converted into number - the first character will become the least significant byte of number.
So it's like NASM but only supporting
0b101 etc. for base 2.
BTW, the first step in dealing with FASM's unhelpful error message was trying a different number syntax, to make sure something like
IN_NUM1 dd 1,2,4 assembled. Since it did, that shows that the syntax for writing numbers was not what FASM wanted, rather than some other part of the syntax.
BTW, you don't need to push and pop your input. Store your data little-endian (least-significant chunk first) or loop backwards if you really want. You can increment pointers or an index without affecting FLAGS by using
dec leave CF unmodified. (Older Intel CPUs (P6-family) will have performance problems in an
adc loop, but Skylake has no flag-merging cost at all.)
inc an negative index up towards zero, and index relative to the ends of the arrays, so your loop logic can be
inc ecx /
jnz. That's pretty good for performance if you're not going to unroll the loop, although
adc reg, [reg + ecx*4] won't micro-fuse even on Skylake (will un-laminate at issue/rename because of the indexed addressing mode).
User contributions licensed under CC BY-SA 3.0