Assembly language and printing result. Fibbonacci sequence - linux
I use Assembly on x86 Linux, with instructions for Intel 8086. I have a problem with my program, which should count the element of Fibbonacci sequence.
This program I run with args, for e.g.:
./fibb 1 2 3 ,
what means: 1st element of sequence is 1, the 2st element is 2 and we want to get the 3rd.
And that example works great, but when I try to run like:
./fibb 1 2 4 ,
then I've got some junk.
Please help me. I'm new in Assembly so please explain me clearly what I'm doing wrong.
Here is my code:
.intel_syntax noprefix
.global _start
.data
var1:
.ascii "To few args\n"
.equ len1, $-var1
var2:
.ascii "Wrong data\n"
.equ len2, $-var2
var3:
.ascii "wrong element of the sequence\n"
.equ len3, $-var3
var4:
.ascii "element of the sequence is higher than 255\n"
.equ len4, $-var4
var5:
.ascii "result: "
.equ len5, $-var5
var6:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
var7:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
var8:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.text
_start:
jmp ety5
ety1:
mov bh, 48
ety2:
cmp [eax], bh
jz ety3
inc bh
cmp bh, 58
jnz ety2
ety3:
cmp bh, 58
jnz ety4
inc bl
ety4:
inc eax
cmp [eax], byte ptr 0
jnz ety1
ret
ety5:
jmp ety10
invert:
xor ecx, ecx
ety6:
inc ebx
inc ecx
cmp [ebx], byte ptr 0
jnz ety6
ety7:
dec ecx
cmp ecx, 0
jz ety8
mov [ebx], byte ptr 0
dec ebx
cmp [ebx], byte ptr 48
jz ety7
inc ebx
ety8:
inc ecx
push ecx
xor ecx, ecx
ety9:
add ecx, 2
push ecx
dec ebx
mov cl, [eax]
mov ch, [ebx]
mov [eax], ch
mov [ebx], cl
inc eax
pop ecx
cmp ecx, [ebp-8]
jb ety9
pop ecx
ret
ety10:
jmp ety18
ety11:
mov cl, [eax]
cmp cl, 0
jz ety12
sub cl, 48
ety12:
mov ch, [ebx]
sub ch, 48
add cl, dh
xor dh, dh
add cl, ch
cmp cl, 10
jb ety13
inc dh
sub cl, 10
ety13:
add cl, 48
mov [eax], cl
inc eax
inc ebx
cmp [ebx], byte ptr 0
jnz ety11
ety14:
cmp [eax], byte ptr 0
jz ety16
mov cl, [eax]
sub cl, 48
add cl, dh
xor dh, dh
cmp cl, 10
jb ety15
sub cl, 10
inc dh
ety15:
add cl, 48
mov [eax], cl
inc eax
jmp ety14
ety16:
cmp dh, 0
jz ety17
add dh, 48
mov [eax], dh
ety17:
ret
ety18:
jmp ety22
ety19:
mov esi, 3
mov dl, [ecx]
sub dl, 48
loop_mul:
add dl, dl
dec esi
cmp esi,0
jnz loop_mul
add dl, dh
xor dh, dh
cmp dl, 10
jb ety20
sub dl,10
inc dh
ety20:
add dl, 48
mov [ebx], dl
inc ebx
inc ecx
cmp [ecx], byte ptr 0
jnz ety19
cmp dh, 0
jz ety21
add dh, 48
mov [ebx], dh
ety21:
mov ebx, offset var8
ret
ety22:
mov ebp, esp
mov eax, [ebp+8]
cmp eax, 0
jnz ety23
mov eax, 4
mov ebx, 1
mov ecx, offset var1
mov edx, offset len1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety23:
mov eax, [ebp+12]
cmp eax, 0
jnz ety24
mov eax, 4
mov ebx, 1
mov ecx, offset var1
mov edx, offset len1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety24:
mov eax, [ebp+16]
cmp eax, 0
jnz ety25
mov eax, 4
mov ebx, 1
mov ecx, offset var1
mov edx, offset len1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety25:
xor bl, bl
mov eax, [ebp+8]
call ety1
mov eax, [ebp+12]
call ety1
cmp bl, 0
jz ety26
mov eax, 4
mov ebx, 1
mov ecx, offset var2
mov edx, offset len2
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety26:
mov eax, [ebp+16]
call ety1
cmp bl, 0
jz ety27
mov eax, 4
mov ebx, 1
mov ecx, offset var3
mov edx, offset len3
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety27:
xor ebx, ebx;
mov eax, [ebp+16]
mov ecx, [ebp+16]
ety28:
cmp [eax], byte ptr 0
jnz ety29
mov eax, 4
mov ebx, 1
mov ecx, offset var3
mov edx, offset len3
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety29:
cmp [eax], byte ptr 48
jnz ety30
inc eax
inc ecx
jmp ety28
ety30:
inc ecx
cmp [ecx], byte ptr 0
jz ety35
inc ecx
cmp [ecx], byte ptr 0
jz ety33
inc ecx
cmp [ecx], byte ptr 0
jz ety31
mov eax, 4
mov ebx, 1
mov ecx, offset var4
mov edx, offset len4
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety31:
mov cl, [eax]
inc eax
sub cl, 48
ety32:
add ebx, 100
dec cl
cmp cl, 0
jnz ety32
ety33:
mov cl, [eax]
inc eax
sub cl, 48
cmp cl, 0
jz ety35
ety34:
add ebx, 10
dec cl
cmp cl, 0
jnz ety34
ety35:
mov cl, [eax]
sub cl, 48
cmp cl, 0
jz ety37
ety36:
inc ebx
dec cl
cmp cl, 0
jnz ety36
ety37:
cmp ebx, 256
jb ety38
mov eax, 4
mov ebx, 1
mov ecx, offset var4
mov edx, offset len4
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety38:
xor dl, dl
ety39:
dec ebx
inc dl
cmp ebx,0
jnz ety39
mov eax, [ebp+12]
mov ebx, offset var7
xor dh, dh
ety40:
inc eax
inc dh
cmp [eax], byte ptr 0
jnz ety40
xor ch, ch
ety41:
dec eax
dec dh
mov cl, [eax]
mov [ebx], cl
inc ebx
cmp dh, 0
jnz ety41
mov eax, [ebp+8]
mov ebx, offset var6
ety42:
inc eax
inc dh
cmp [eax], byte ptr 0
jnz ety42
ety43:
dec eax
dec dh
mov cl, [eax]
mov [ebx], cl
inc ebx
cmp dh, 0
jnz ety43
cmp dl, 1
jnz ety44
jmp ety46
ety44:
dec dl
cmp dl, 1
jnz ety45
jmp ety47
ety45:
dec dl
cmp dl, 0
jz ety47
push edx
xor dh, dh
mov eax, offset var6
mov ebx, offset var8
mov ecx, offset var7
call ety19
xor dh, dh
call ety11
pop edx
dec dl
cmp dl, 0
jz ety46
push edx
xor dh, dh
mov eax, offset var7
mov ebx, offset var8
mov ecx, offset var6
call ety19
xor dh, dh
call ety11
pop edx
jmp ety45
ety46:
mov eax, 4
mov ebx, 1
mov ecx, offset var5
mov edx, offset len5
int 0x80
mov eax, offset var6
mov ebx, offset var6
call invert
mov eax, 4
mov ebx, 1
mov edx, ecx
mov ecx, offset var6
int 0x80
mov eax, 4
mov ebx, 1
mov [ecx], byte ptr 10
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety47:
mov eax, 4
mov ebx, 1
mov ecx, offset var5
mov edx, offset len5
int 0x80
mov eax, offset var7
mov ebx, offset var7
call invert
mov eax, 4
mov ebx, 1
mov edx, ecx
mov ecx, offset var7
int 0x80
mov eax, 4
mov ebx, 1
mov [ecx], byte ptr 10
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
int 0x80
This code supposedly fills EAX with the first parameter (a number, not an address).
mov eax, [ebp+8]
call ety1
But at ety1 this code compares the byte at the address EAX with BH.
ety1:
mov bh, 48
ety2:
cmp [eax], bh
jz ety3
How is that going to work?
EDIT
By the time I arrived at the real entry point of this program through a ridiculously long cascade of jumps I totally forgot that this is in fact an application and not just some subroutine. Parameters are thus addresses rendering my answer void!
EDIT2
Are you sure the DS register is properly initialized?
Related
Assembly function on strings
I made function which should return the number of the highest sequence of the same character in a string. So in case of string 'aabbbcaaaabbccc' it should be 4, in case of 'aaaaa' it should be 5. So for 'aaaaa' this function should return 5, actually it returns 2. I am staring on it long time, but I can't see a mistake. unsigned long najdlhsia(const char *vstup) { __asm { mov eax, 0 mov ecx, 0 mov ebx, vstup cmp [ebx], 0 je k mov edx, [ebx] add ebx, 1 inc eax inc ecx c: cmp byte ptr[ebx], 0 je p cmp [ebx], edx jne a1 inc ecx add ebx, 1 jmp c a1: cmp ecx, eax jng a2 mov eax, ecx a2: mov ecx, 1 mov edx, [ebx] add ebx, 1 jmp c p: cmp ecx, eax jng k mov eax, ecx k: } } int main() { printf("%d", najdlhsia("aaaaa")); return 0; }
IA-32 beginner asm sys_write confusion
I'm using NASM, IA-32 (I think). The homework is to take ASCII from a .txt file and print it to the console in hexadecimal using linux shell input redirection. I think I've got the ascii to hex part figured out, but I'm having a hard time making it print the console correctly. I'm sure I'm just missing something small and silly. The file I'm reading just to test is something simple like this: ABC 123 The output should be: 41 42 43 0A 31 20 32 20 33 20 The problem is happening in _hexOut: I've tried changing more stuff around than I can fit in this post, and I can't figure out where I'm going wrong. The only output I'm getting is: 41 42 43 section .text global _start _start: mov edx, inBuffSize ; sys_read mov ecx, inBuffer ; - mov ebx, 0x00 ; - mov eax, 0x03 ; - int 0x80 ; end sys_read mov [inputLen], eax cmp eax, 0 jle _exit _inLeft: mov ecx, [inCount] ; move cmp ecx, [inputLen] je _hexOut movzx eax, byte [inBuffer + ecx] mov [temp], al shr al, 4 mov bl, 9 cmp al, bl jle _leftIsNumber mov bl, 10 cmp al, bl jge _leftIsLetter _leftIsNumber: mov ecx, [outCount] add al, 48 mov [outBuffer + ecx], al mov ecx, [outCount] inc ecx mov [outCount], ecx jmp _inRight _leftIsLetter: mov ecx, [outCount] add al, 55 mov [outBuffer + ecx], al mov ecx, [outCount] inc ecx mov [outCount], ecx jmp _inRight _inRight: mov ecx, [inCount] inc ecx mov [inCount], ecx movzx eax, byte [temp] and al, 0x0F mov bl, 9 cmp al, bl jle _rightIsNumber mov bl, 10 cmp al, bl jge _rightIsLetter _rightIsNumber: mov ecx, [outCount] add al, 48 mov [outBuffer + ecx], al mov ecx, [outCount] inc ecx mov [outBuffer + ecx], byte 32 inc ecx mov [outCount], ecx jmp _inLeft _rightIsLetter: mov ecx, [outCount] add al, 55 mov [outBuffer + ecx], al mov ecx, [outCount] inc ecx mov [outBuffer + ecx], byte 32 inc ecx mov [outCount], ecx jmp _inLeft _hexOut:;------------------ PROBLEMS HERE ---------------------- ; mov ecx, [inputLen] ; mov [outCount + ecx], byte 0x0A ; inc ecx ; mov [inputLen], ecx mov edx, [inputLen] mov ecx, outBuffer mov ebx, 0x01 mov eax, 0x04 int 0x80 ;------------------------------------------------------ _exit: mov ebx, 0 mov eax, 1 int 0x80 section .data section .bss inBuffer resb inBuffSize outBuffer resb outBuffSize inBuffSize equ 200 outBuffSize equ 600 inCount resd 1 outCount resd 1 temp resb 1 inputLen resd 1 The second part of the problem is that I need to be able to change how many hex bytes are shown per line in the console, but I can't start to tackle that until I get the first problem solved. Any nudge in the right direction would be appreciated!
nasm 32 word division always giving 1 as an answer
I've been trying to divide a word sized variables and the resulting quotient is always 1 and the remainder is always dividend-divisor. What could have gone wrong? Thank you in advance. section .data section .bss num1a resw 1 num1b resw 1 num2a resw 1 num2b resw 1 section .text global _start _start: ;get inputs mov eax, 3 mov ebx, 0 mov ecx, num1a mov edx, 1 int 80h mov eax, 3 mov ebx, 0 mov ecx, num1b mov edx, 2 int 80h mov eax, 3 mov ebx, 0 mov ecx, num2a mov edx, 1 int 80h mov eax, 3 mov ebx, 0 mov ecx, num2b mov edx, 2 int 80h ;convert sub word[num1a], 30h sub word[num1b], 30h sub word[num2a], 30h sub word[num2b], 30h mov ax, 0 mov bx, 0 mov ax, [num1a] mov bx, 10 mul bx add ax, [num1b] mov word[num1a], ax mov ax, 0 mov bx, 0 mov ax, [num2a] mov bx, 10 mul bx add ax, [num2b] mov word[num2a], ax ;divide mov ax, 0 mov dx, 0 mov ax, [num1a] div word[num2a] mov word[num1a], ax mov word[num2a], dx mov ax, 0 mov dx, 0 mov ax, [num1a] mov bx, 10 div bx mov word[num1a], ax mov word[num2a], dx ;convert add word[num1a], 30h add word[num2a], 30h ;print mov eax, 4 mov ebx, 1 mov ecx, num1a mov edx, 1 int 80h mov eax, 4 mov ebx, 1 mov ecx, num2a mov edx, 1 int 80h exit: mov eax, 1 mov ebx, 0 int 80h
Basic assembly calculator assignment not working
We need to do addition, subtraction, multiplication and division with single digits that are entered in using syscalls. For some reason my addition is the only thing that works. I cannot figure out why the rest don't work. All of them outputs nothing, except for multiplication that works if you multiply by 1. My subtract code: segment .data one db 0 two db 0 diff db 0 segment .text global _start _start: mov rax, 0 mov rdi, 0 lea rsi, [one] mov rdx, 2 syscall mov rbx, [one] sub rbx, 48 mov rax, 0 mov rdi, 0 lea rsi, [two] mov rdx, 2 syscall sub rbx, [two] mov [diff], rbx ;xor rbx, rbx mov rax, 1 mov rdi, 1 mov rdx, 1 lea rsi, [diff] syscall mov rax, 60 xor rdi, rdi syscall My multiplication code: segment .data one db 0 two db 0 multi db 0 segment .text global _start _start: mov eax, 0 mov edi, 0 lea esi, [one] mov edx, 2 syscall ;mov ebx, [one] ;sub ebx, '0' mov eax, 0 mov edi, 0 lea rsi, [two] mov edx, 2 syscall mov eax, [one] sub eax, '0' ;mov ecx, [two] ;sub ecx, '0' mul dword [two] mov [multi], eax xor edx, edx mov eax, 1 mov edi, 1 mov edx, 1 lea esi, [multi] syscall mov eax, 60 xor edi, edi syscall And division code: segment .data one db 0 two db 0 qout db 0 segment .text global _start _start: mov rax, 0 mov rdi, 0 lea rsi, [one] mov rdx, 2 syscall ;mov rbx, [one] ;sub rbx, '0' mov rax, 0 mov rdi, 0 lea rsi, [two] mov edx, 2 syscall mov eax, [one] sub eax, '0' mov edx, 0 mov ecx, two ;sub ecx, '0' div ecx mov [qout], [rax] ;xor rdx, rdx mov rax, 1 mov rdi, 1 mov rdx, 1 lea rsi, [qout] syscall mov rax, 60 xor rdi, rdi syscall Can someone please tell me why this is not working. This is my addition for reference: segment .data one db 0 two db 0 sum db 0 segment .text global _start _start: mov eax, 0 ;read mov edi, 0 ;file descriptor lea esi, [one] ;write to one mov edx, 2 ;size of input in bytes syscall mov ebx, [one] sub ebx, '0' ;'convert' to int mov eax, 0 ;again another input mov edi, 0 lea rsi, [two] mov edx, 2 syscall add ebx, [two] ;add two to one mov [sum], ebx ;move sum into [sum] xor ebx, ebx ;clear the register mov eax, 1 ;syscall write mov edi, 1 ;file descriptor mov edx, 1 ;output one byte lea esi, [sum] ;output sum syscall mov eax, 60 ;syscall 60 is exit xor edi, edi ;exit(0) syscall
I found a solution. In my code I subtracted '0' from both numbers and after the operation I just added '0' again.For Division I did what the solution to this question suggested.
Segmentation issue NASM
I'm working on conversions of c programs to NASM and I've been having issues with segmentation faults after the program runs. It will do what its supposed to do but will provide a segmentation fault message at the end of it. The code is: segment .data out_less db "Z is less than 20.", 10, 0 out_greater db "Z is greater than 20.", 10, 0 out_equal db "Z is equal to 20! Yeah Z!", 10, 0 segment .bss segment .text global main extern printf ret main: mov eax, 10 mov ebx, 12 mov ecx, eax add ecx, ebx ;set c (ecx reserved) mov eax, 3 mov ebx, ecx sub ebx, eax ;set f (ebx reserved) mov eax, 12 mul ecx add ecx, 10 ;(a+b*c) (ecx reserved) mov eax, 6 mul ebx mov eax, 3 sub eax, ebx mov ebx, eax ;(d-e*f) (ebx reserved) reassign to ebx to keep eax open for manipulation mov eax, ecx div ebx mov ecx, eax add ecx, 1 ;(a+b*c)/(d-e*f) + 1 cmp ecx, 20 jl less jg greater je equal mov eax, 0 ret less: push out_less call printf ret jmp end greater: push out_greater call printf ret jmp end equal: push out_equal call printf ret jmp end end: mov eax, 0 ret I'm not sure whats causing the fault because the program does actually run correctly any thoughts? Thanks!
Update - this seems to work: segment .data out_less db "Z is less than 20.", 10, 0 out_greater db "Z is greater than 20.", 10, 0 out_equal db "Z is equal to 20! Yeah Z!", 10, 0 segment .bss segment .text global main extern printf main: mov eax, 10 mov ebx, 12 mov ecx, eax add ecx, ebx ;set c (ecx reserved) mov eax, 3 mov ebx, ecx sub ebx, eax ;set f (ebx reserved) mov eax, 12 mul ecx add ecx, 10 ;(a+b*c) (ecx reserved) mov eax, 6 mul ebx mov eax, 3 sub eax, ebx mov ebx, eax ;(d-e*f) (ebx reserved) reassign to ebx to keep eax open for manipulation mov eax, ecx div ebx mov ecx, eax add ecx, 1 ;(a+b*c)/(d-e*f) + 1 cmp ecx, 20 jl less jg greater jmp equal less: push out_less call printf add esp,4 jmp exit greater: push out_greater call printf add esp,4 jmp exit equal: push out_equal call printf add esp,4 exit: mov eax, 0 ret end