NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: Eght on January 03, 2017, 07:23:53 PM
-
Hi guys.
I have to understand how this program works. All comments are mine. Could someone make me sure my thoughts are valid? Thisprogram count 128 bit factorial. Why there are not any mul instructions? All additional comments are welcome : )
;128 bits is too big for mul instruction,
;which saves only 64-bits result (EDX (32bits) + EAX (32bits)).
;So first of all you need 4 DWORDS of memory to store 128bits result.
;Then you should replace your mul ebx; on some procedure call,
;that can handle 128bits multiplication.
SECTION .data
formatd: db "%d", 0 ; integer??
formatx: db "%08x", 0 :??
name: resb 20 ;reserve 20 bytes, they declare uninitialized storage space.
number: resb 4
array resd 4
backup resd 4
SECTION .text
extern printf
extern scanf
global main
main:
push EBP
mov EBP, ESP ;base pointer, stack pointer
push number
push formatd
call scanf
add ESP, 8 ; all: read number
mov ebx, dword [number]
mov dword [array+0], 0x0 ;initialize with zeros
mov dword [array+4], 0x0
mov dword [array+8], 0x0
mov dword [array+16], 0x0
mov dword [backup+0], 0x0
mov dword [backup+4], 0x0
mov dword [backup+8], 0x0
mov dword [backup+16], 0x0
mov [array+0], eax
outer_loop:
cmp ebx, 0x1
je end
mov eax, [array+0] ;assignment a numbers to the array
mov [backup+0], eax
mov eax, [array+4]
mov [backup+4], eax
mov eax, [array+8]
mov [backup+8], eax
mov eax, [array+12]
mov [backup+12], eax
mov ecx, ebx
dec ecx
inner_loop:
clc
; adding 128 bit number
mov eax, [backup+0]
adc [array+0], eax ;add carried part from previous multiplication
mov eax, [backup+4]
adc [array+4], eax
mov eax, [backup+8]
adc [array+8], eax
mov eax, [backup+12]
adc [array+12], eax
clc ;Clear carry flag
loop inner_loop ; uses ecx (or cx in 16-bit code)
dec ebx
jmp outer_loop
end:
push dword [array+12] ; printing number
push formatx
call printf
add ESP, 8
push dword [array+8]
push formatx
call printf
add ESP, 8
push dword [array+4]
push formatx
call printf
add ESP, 8
push dword [array+0]
push formatx
call printf
add ESP, 8
mov ESP, EBP
pop EBP
ret
-
Hi Eght,
Oh goody! Two programs at once! :)
The first thing that jumps out at me:
mov dword [array+0], 0x0 ;initialize with zeros
mov dword [array+4], 0x0
mov dword [array+8], 0x0
mov dword [array+16], 0x0
mov dword [backup+0], 0x0
mov dword [backup+4], 0x0
mov dword [backup+8], 0x0
mov dword [backup+16], 0x0
The "16"s need to be "12"s. You get this right later on.
My guess as to why there are no "mul" instructions is that the 128-bit "mul" is done by repeated "add"s. I think I'm going to have to assemble this and try it out to see how it works.
You'll have to forgive me. I'm old and tired and a bit depressed. I used to be better at this, honest. I'd leave this for someone younger to answer, but sometimes when I don't answer a question it doesn't get answered at all (which makes me even more depressed). I'll try to get back to this...
In order to get 128 bits out of "printf", you concatenate hex numbers. In order to compare what we print to the "known" good answer to factorial, we're going to have to convert back and forth to decimal (this is a reminder to myself as well as you).
Later,
Frank
-
;128 bits is too big for mul instruction,
;which saves only 64-bits result (EDX (32bits) + EAX (32bits)).
;So first of all you need 4 DWORDS of memory to store 128bits result.
;Then you should replace your mul ebx; on some procedure call,
;that can handle 128bits multiplication.
SECTION .data
formatd: db "%d", 0 ; integer??
formatx: db "%08x", 0 :?? <- semicolon, not colon - it calls for 8 bytes of hex
; Nasm warns about this. No harm. but to shut it up:
section .bss
name: resb 20 ;reserve 20 bytes, they declare uninitialized storage space.
number: resb 4
; "resd 1" does the same thing - might be clearer?
array resd 4
backup resd 4
SECTION .text
extern printf
extern scanf
global main
main:
push EBP
mov EBP, ESP ;base pointer, stack pointer
push number
push formatd
call scanf
add ESP, 8 ; all: read number
mov ebx, dword [number]
mov dword [array+0], 0x0 ;initialize with zeros
mov dword [array+4], 0x0
mov dword [array+8], 0x0
mov dword [array+12], 0x0
mov dword [backup+0], 0x0
mov dword [backup+4], 0x0
mov dword [backup+8], 0x0
mov dword [backup+12], 0x0
mov [array+0], eax
; at this point, eax is the return from scanf. Not sure you want that here.
... more later?
Best,
Frank