I’m very new to assembly and having difficulties in getting basic calculations to work with different length numbers.
So this is my adding code, that works with numbers that are 3 or less characters long. for as long as both are the same length. for example 123 + 123 works just fine and outputs 246. But 12 + 123 does not work and it outputs 253 as the answer. How would I be able to get this working with different length numbers?
JavaScript
x
sys_exit equ 1
sys_read equ 3
sys_write equ 4
stdin equ 0
stdout equ 1
section .data
newLine db 10
cquestion db 'Enter a number: ', 0xa
cqLen equ $ - cquestion
answer db 'Your answer is: '
aLen equ $ - answer
section .bss
number1 resb 4
number2 resb 4
number1Len resd 1
number2Len resd 1
answ resb 8
%macro write_string 2
mov eax, 4
mov ebx, 1
mov ecx, %1
mov edx, %2
int 0x80
%endmacro
section .text
global _start
_start:
write_string cquestion, cqLen
mov eax, sys_read
mov ebx, stdin
mov ecx, number1
mov edx, 4
int 0x80
mov [number1Len], eax
write_string cquestion, cqLen
mov eax, sys_read
mov ebx, stdin
mov ecx, number2
mov edx, 4
int 0x80
mov [number2Len], eax
write_string answer, aLen
clc
mov ecx, [number2Len] ;number of digits
dec ecx ;need to decrease one for some reason?
mov esi, ecx
dec esi ;pointing to the rightmost digit.
.add_loop:
mov al, [number1 + esi]
adc al, [number2 + esi]
aaa
pushf ; also no idea what this is here for
or al, 30h ; or this
popf ; and this
mov [answ + esi], al
dec esi
loop addition.add_loop
mov eax, sys_write
mov ebx, stdout
mov ecx, answ
mov edx, 8
int 0x80
mov eax, sys_write
mov ebx, stdout
mov ecx, newLine
mov edx, 1
int 0x80
mov [answ], DWORD 0
Advertisement
Answer
- Your loop never does more than 3 iterations. If there’s a final carry, you’ll need an extra write to the destination.
- If the code needs to deal with different length inputs, then you can’t use the same offset
ESI
to address corresponding digits from both numbers. - And neither can you use that same
ESI
to store the output since you could need one extra position to the left. - About
answ resb 8
, summing a couple of 3-digit numbers can at most produce a 4-digit sum.
Below is one of the many solutions to this question.
JavaScript
ECX=1
v
num1: 31 32 0A 00 31 32 30 30
num2: 31 32 33 0A 31 32 33 30
^
EDX=2
answ: 00 00 00 00 --> 30 31 33 35
^
EDI=3
JavaScript
mov ecx, [number1Len] ; Number of bytes (eg. 3)
sub ecx, 2 ; Offset to 'ones' digit
lea eax, [ecx + 1] ; Offset to the newline
.more1:
mov byte [number1 + eax], 30h
inc eax
test eax, 3
jnz .more1
mov edx, [number2Len] ; Number of bytes (eg. 4)
sub edx, 2 ; Offset to 'ones' digit
lea eax, [edx + 1] ; Offset to the newline
.more2:
mov byte [number2 + eax], 30h
inc eax
test eax, 3
jnz .more2
mov edi, 3 ; 4 iterations
clc
.add_loop:
movzx eax, byte [number1 + ecx]
adc al, [number2 + edx]
aaa
lahf ; Preserves CF gotten from `aaa`
or al, 30h ; Convert into character "0" to "9"
mov [answ + edi], al
dec ecx
and ecx, 3 ; Wraparound in number1
dec edx
and edx, 3 ; Wraparound in number2
sahf ; Restores CF
dec edi
jns .add_loop
In the result in answ we can remove at most 3 leading zeroes. If the true result is 0, the 4th character in answ would have to remain.
JavaScript
mov edx, 4
mov ecx, answ
.del:
cmp byte [ecx], 30h
jne .ok
dec edx
inc ecx
cmp edx, 1
ja .del
.ok:
mov ebx, stdout
mov eax, sys_write
int 80h