Display First N Fibonacci Numbers in x86 asm [duplicate] - visual-studio

This question already has answers here:
MASM x86 Adding two ints
(1 answer)
What is the Irvine32 library and why do we use it?
(1 answer)
x86 Assembly Input a set of Integers
(1 answer)
Closed 2 years ago.
I want to generate the 1st N fibonacci numbers in x86 asm using the Irvine Library. That means whenever I will give N = 5, it should print : 0,1,1,2,3, But whenever I run it suppose with N =5 then it gives output as : 0,1,2,3,4.
Below is my program
TITLE MASM Irvine
INCLUDE Irvine32.inc
.data
message1 BYTE "The first ",0
message2 BYTE " numbers in the Fibonacci sequence are the following.",0
N DWORD 10
intialVal WORD 0,1
.code
main PROC
call Clrscr ; clears screen
mov edx,OFFSET message1
call WriteString ; display message1
mov eax, N
call WriteDec ; display num
mov edx,OFFSET message2
call WriteString ; display message2
call Crlf ; new line
mov eax,0
mov bx, [intialVal]
mov cx, [intialVal + 2]
StartLoop:
mov edx,0 ;setting edx to 0 every time
add dx,bx ;adding bx to dx
add dx,cx ;adding cx to dx
call WriteDec
call Crlf ;trying to print dx
mov bx,cx ;moving numbers. so now cx goes to bx
mov cx,dx ;dx goes to cx
inc eax ;increment eax (as a counter)
cmp eax,N ;compare to variable N
jne StartLoop ;if eax = N exit loop, else jump to start of loop
exit
main ENDP
END main

Related

No output from 8086 program when running ml program.asm in DOSBox

I got this code from the Geeks-for-Geeks site, but there were lots of indentation errors, I changed the code to the following but, when running the code using MASM and DOSBox it's giving no output.
The Output I should get, According to the site I should get 20 but I get nothing, the code is saved as pro.asm, and I'm using DOSBox version 0.74.
For getting the o/p in the DOSBox I did,
mount c c:\8086
c:
ml pro.asm
Code:
;8086 program to convert a 16-bit decimal number to octal
.MODEL SMALL
.STACK 100H
.DATA
d1 dw 16
.CODE
MAIN PROC FAR
MOV ax,#DATA
MOV ds,ax
;load the value stored in variable d1
MOV ax, d1
;convert the value to octal
;print the value
CALL PRINT
;interrupt to exit
MOV AH,4CH
INT 21H
MAIN ENDP
PRINT PROC
;initialize count
MOV cx,0
MOV dx,0
label1: ;if ax is zero
cmp ax,0
je print1
;initialize bx to 8
mov bx, 8
;divide it by 8 to convert it to octal
div bx
;push it in the stack
push dx
;increment the count
inc cx
;set dx to 0
xor dx,dx
jmp label1
print1: ;check if count is greater than zero
cmp cx,0
je exit
;pop the top of stack
pop dx
;add 48 so that it
;represents the ASCII
;value of digits
add dx,48
;interrupt to print a
;character
mov ah,02h
int 21h
;decrease the count
dec cx
jmp print1
exit : ret
PRINT ENDP
END MAIN
The output I'm getting can be seen below
Your code looks okay. Your screenshot shows you have only assembled and linked the code but not actually run it. To run it type:
pro.exe

x86 Program received signal SIGSEGV, Segmentation fault during debugging MASM32 assembly

I am tasked with writing my first assembly code which takes a number between 1-12 entered by the user and outputs the factorial. I need to write 3 procedures one for the input, one to calculate factorial and one to print the result. I believe I have written it correctly (I didn't) but after getting the input from the user, the program terminates. I never see the result of my "Print" procedure. When trying to debug my code I get the error:
Program received signal SIGSEGV, Segmentation fault.
This error comes right after the first step of "invoke input"
Here is my complete code :
include c:\asmio\asm32.inc
includelib c:\asmio\asm32.lib
includelib c:\asmio\User32.lib ; SASM files for I/O
includelib c:\asmio\Kernel32.lib ; SASM files for I/O
input proto ; 0 parameters
Factorial proto nvx: dword ; 1 parameter
Print proto nax: dword, nf: dword ; 2 parameters
; -------------------------------------------------------
.const ; Section to declare and initialize constants
NULL = 0
; -------------------------------------------------------
.data ; Section to declare and initialize variables
nvx dword ?
nfx dword ?
nf dword ?
ask byte "Enter a number between 1-12: ", NULL
fin byte "! is ", NULL
; -------------------------------------------------------
.code ; The actual code begins here: Main program
main proc ; Just like C++ this is the main program
start:
invoke input
mov nvx, eax
invoke Factorial, nvx
mov nfx, eax
invoke Print, nvx, nfx
ret 0 ; need this line to return to caller
main endp ; End of the procedure main
; -------------------------------------------------------
input proc
mov edx, OFFSET ask
call WriteString
call ReadInt
ret
input endp
; -------------------------------------------------------
Factorial proc USES ECX EBX nv: dword
mov ecx, nv ;start loop counter at value given by user because we need to multiply this many times to find the factorial.
mov ebx, nv ; hold value of nv as divisor
inc nv ; This is to account for 0! We increment by one and after the loop divide by nv
mov eax, nv ; stores the largest number for multiplication
L1:
dec nv ; becomes next largest number
mul nv ; multiplication
mov eax, edx ; stores product into eax for next multiplication
loop L1
inc ebx
cdq
idiv ebx ; divide final product by original number + 1 for the correct factorial
ret
Factorial endp
Print proc nax: dword, na: dword
mov eax, nvx
call WriteString
mov eax, OFFSET fin
call WriteString
mov eax, na
call WriteString
ret
Print endp
end main ; End of the entire program
; -------------------------------------------------------

How to print signed integer in x86 assembly (NASM) on Mac

I found an implementation of unsigned integer conversion in x86 assembly, and I tried plugging it in but being new to assembly and not having a debugging env there yet, it's difficult to understand why it's not working. I would also like it to work with signed integers so it can capture error messages from syscalls.
Wondering if one could show how to fix this code to get the signed integer to print, without using printf but using strprn provided by this answer.
%define a rdi
%define b rsi
%define c rdx
%define d r10
%define e r8
%define f r9
%define i rax
%define EXIT 0x2000001
%define EXIT_STATUS 0
%define READ 0x2000003 ; read
%define WRITE 0x2000004 ; write
%define OPEN 0x2000005 ; open(path, oflag)
%define CLOSE 0x2000006 ; CLOSE
%define MMAP 0x2000197 ; mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset)
; szstr computes the lenght of a string.
; rdi - string address
; rdx - contains string length (returned)
strsz:
xor rcx, rcx ; zero rcx
not rcx ; set rcx = -1 (uses bitwise id: ~x = -x-1)
xor al,al ; zero the al register (initialize to NUL)
cld ; clear the direction flag
repnz scasb ; get the string length (dec rcx through NUL)
not rcx ; rev all bits of negative -> absolute value
dec rcx ; -1 to skip the null-term, rcx contains length
mov rdx, rcx ; size returned in rdx, ready to call write
ret
; strprn writes a string to the file descriptor.
; rdi - string address
; rdx - contains string length
strprn:
push rdi ; push string address onto stack
call strsz ; call strsz to get length
pop rsi ; pop string to rsi (source index)
mov rax, WRITE ; put write/stdout number in rax (both 1)
mov rdi, 1 ; set destination index to rax (stdout)
syscall ; call kernel
ret
; mov ebx, 0xCCCCCCCD
itoa:
xor rdi, rdi
call itoal
ret
; itoa loop
itoal:
mov ecx, eax ; save original number
mul ebx ; divide by 10 using agner fog's 'magic number'
shr edx, 3 ;
mov eax, edx ; store quotient for next loop
lea edx, [edx*4 + edx] ; multiply by 10
shl rdi, 8 ; make room for byte
lea edx, [edx*2 - '0'] ; finish *10 and convert to ascii
sub ecx, edx ; subtract from original number to get remainder
lea rdi, [rdi + rcx] ; store next byte
test eax, eax
jnz itoal
exit:
mov a, EXIT_STATUS ; exit status
mov i, EXIT ; exit
syscall
_main:
mov rdi, msg
call strprn
mov ebx, -0xCCCCCCCD
call itoa
call strprn
jmp exit
section .text
msg: db 0xa, " Hello StackOverflow!!!", 0xa, 0xa, 0
With this working it will be possible to properly print signed integers to STDOUT, so you can log the registers values.
https://codereview.stackexchange.com/questions/142842/integer-to-ascii-algorithm-x86-assembly
How to print a string to the terminal in x86-64 assembly (NASM) without syscall?
How do I print an integer in Assembly Level Programming without printf from the c library?
https://baptiste-wicht.com/posts/2011/11/print-strings-integers-intel-assembly.html
How to get length of long strings in x86 assembly to print on assertion
My answer on How do I print an integer in Assembly Level Programming without printf from the c library? which you already linked shows that serializing an integer into memory as ASCII decimal gives you a length, so you have no use for (a custom version of) strlen here.
(Your msg has an assemble-time constant length, so it's silly not to use that.)
To print a signed integer, implement this logic:
if (x < 0) {
print('-'); // or just was_negative = 1
x = -x;
}
unsigned_intprint(x);
Unsigned covers the abs(most_negative_integer) case, e.g. in 8-bit - (-128) overflows to -128 signed. But if you treat the result of that conditional neg as unsigned, it's correct with no overflow for all inputs.
Instead of actually printing a - by itself, just save the fact that the starting number was negative and stick the - in front of the other digits after generating the last one. For bases that aren't powers of 2, the normal algorithm can only generate digits in reverse order of printing,
My x86-64 print integer with syscall answer treats the input as unsigned, so you should simply use that with some sign-handling code around it. It was written for Linux, but replacing the write system call number will make it work on Mac. They have the same calling convention and ABI.
And BTW, xor al,al is strictly worse than xor eax,eax unless you specifically want to preserve the upper 7 bytes of RAX. Only xor-zeroing of full registers is handled efficiently as a zeroing idiom.
Also, repnz scasb is not fast; about 1 compare per clock for large strings.
For strings up to 16 bytes, you can use a single XMM vector with pcmpeqb / pmovmskb / bsf to find the first zero byte, with no loop. (SSE2 is baseline for x86-64).

assembly: sorting numbers using only conditional statments

I am new to assembly and I am trying to write a program that gets five user inputed numbers, stores them in variables num1-num5, sorts them(without using arrays) with num5 having the greatest value and num1 having the lowest value, and then displays the sorted numbers. I am having trouble figuring out how to approach this. I got the 5 numbers and stored them in the variables but I am confused as to how to start with sorting. I have tried a few things but I keep getting errors. This is my code that I can actually get running but it isn't working the way I want it to.
TITLE MASM Template (main.asm)
INCLUDE Irvine32.inc
.data
getnumber byte "Please enter a number between 0 and 20",0ah,0dh,0
num1 byte 0
num2 byte 0
num3 byte 0
num4 byte 0
num5 byte 0
.code
main PROC
call Clrscr
;************* get the information from the user*******************
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl, al
mov num1, bl ;get the number and move to num1 variable
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl, al
mov num2, bl ;get the number and move to num2 variable
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl, al
mov num3, bl ;get the number and move to num3 variable
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl,al
mov num4, bl ;get the number and move to num4 variable
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl, al
mov num5, bl ;get the number and move to num5 variable
;***show the user inputed numbers****
mov al, num1
call writeint
mov al, num2
call writeint
mov al,num3
call writeint
mov al, num4
call writeint
mov al,num5
call writeint
;*****start comparing***
cmp bl,num5
jl jumptoisless
jg jumptoisgreater
jumptoisless:
call writeint
jumptoisgreater:
mov bl, num5
mov dl, num4
mov num5, dl
mov num4, bl
call writeint
jmp imdone
imdone:
call dumpregs
exit
main ENDP
END main
Some notes to your code:
call readint
mov bl, al
mov num2, bl
Why don't you simply store al directly to memory, as: mov [num2],al? You don't use the bl anyway.
Except here:
;*****start comparing***
cmp bl,num5
jl jumptoisless
jg jumptoisgreater
Where I would be afraid what call writeint does to ebx (or you did your homework, and you know from head that call writeint preserves ebx content?).
And if the ebx is preserved, then bl contains still num5 from the input, so it will be equal.
Funnily enough, when equal, you will continue with jumptoisless: part of code, which will output some leftover in al, and then it will continue to jumptoisgreater: part of code, so effectively executing all of them.
Can you watch the CPU for a while in debugger, while single stepping over the instructions, to understand a bit better how it works? It's a state machine, ie. based on the current values in registers, and content of memory, it will change the state of registers and memory in the deterministic way.
So unless you jump away, next instructions is executed after the current one, and jl + jg doesn't cover "equal" state (at least you do cmp only once, so hopefully you understand the jcc instructions don't change flags and both jl/jg operate on the same result of cmp in flags). The Assembler doesn't care about name of your labels, and it will not warn you the "isgreater" code is executed even when "isless" was executed first.
About how to solve your task:
Can't think of anything reasonably short, unless you start to work with num1-num5 memory as array, so you can address it in generic pointer way with index. So I will gladly let you try on your own, just a reminder you need at least n*log_n compares to sort n values, so if you would write very effective sort code, you would need at least 5*3 = 15 cmp instructions (log2(5) = 3, as 23 = 8).
On the other hand an ineffective (but simple to write and understand) bubble sort over array can be done with single cmp inside two loops.
rcgldr made me curious, so I have been trying few things...
With insertion sort it's possible to use only 8x (at most) cmp (I hope the pseudo-syntax is understandable for him):
Insert(0, num1)
// ^ no cmp
Insert((num2 <= [0] ? 0 : 1), num2)
// ^ 1x cmp executed
Insert((num3 <= [0] ? 0 : (num3 <= [1] ? 1 : 2)), num3)
// ^ at most 2 cmp executed
Insert((num4 <= [1] ? (num4 <= [0] ? 0 : 1) : (num4 <= [2] ? 2 : 3)), num4)
// ^ always 2 of 3 cmp executed
Insert((num5 <= [1] ? (num5 <= [0] ? 0 : 1) : (num5 <= [2] ? 2 : (num5 <= [3] ? 3 : 4))), num5)
// ^ at most 3 of 4 cmp executed
=> total at most 8 cmp executed.
Of course doing the "insert" with "position" over fixed variables would be total PITA... ;) So this is half-joke proposal just to see if 8x cmp is enough.
("6 compares" turned out to be my brain-fart, not possible AFAIK)

Outputting registers to the console with MASM

I'm one day into learning ASM and I've done a few tutorials, and even successfully modified the tutorial content to use jmp and cmp, etc instead of the MASM .if and .while macros.
I've decided to try and write something very, very simple to begin with before I continue with more advanced tutorials. I'm writing a Fibonacci number generator. Here is the source I have so far:
.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
.code
start:
mov eax, 1
mov ecx, 1
_a:
push eax
add eax, ecx
pop ecx
; Jump to _b if there is an overflow on eax
; Print Values Here
jmp _a
_b:
push 0
call ExitProcess
end start
I intend to check for overflows on eax/ecx but right now I'm just interested in displaying the values of eax/ecx on the screen.
I know how to push the address of a constant string from .data and call StdOut which was the first example in the hello world tutorial, but this appears to be quite different (?).
There is this code provided by Microsoft itself
http://support.microsoft.com/kb/85068
Note that this code outputs AX register on 16 bit systems. But you can get the idea, you just need to convert AX value into ASCII characters by looping through each character. Skip the interrupts part and use your StdOut function.
mov dx, 4 ; Loop will print out 4 hex characters.
nexthex:
push dx ; Save the loop counter.
mov cl, 4 ; Rotate register 4 bits.
rol ax, cl
push ax ; Save current value in AX.
and al, 0Fh ; Mask off all but 4 lowest bits.
cmp al, 10 ; Check to see if digit is 0-9.
jl decimal ; Digit is 0-9.
add al, 7 ; Add 7 for Digits A-F.
decimal:
add al, 30h ; Add 30h to get ASCII character.
mov dl, al
;Use StdOut to print value of dl
;mov ah, 02h ; Prepare for interrupt.
;int 21h ; Do MS-DOS call to print out value.
pop ax ; Restore value to AX.
pop dx ; Restore the loop counter.
dec dx ; Decrement loop counter.
jnz nexthex ; Loop back if there is another character
; to print.
See here as well:
http://www.masm32.com/board/index.php?PHPSESSID=fa4590ba57dbaad4bc44088172af0b49&action=printpage;topic=14410.0

Resources