NASM JLE: Jump if Less or Equal always evaluating to true - nasm

I have code here that reads in input to determine the dimensions of a matrix/2d array and then reads in numbers one by one. Then it is SUPPOSED to spit out the smallest number.
However my comparison operator doesn't seem to be working? I've tried putting both as registers, with different variables and so on but for some reason eax with whatever happened to be the first entry in the array is ALWAYS smaller than the next number, even if this is clearly not the case.
So it always skips reassignment.
Code: Just skip straight to cmp eax,[num]
My guess is something is causing num, perhaps how its declared? Is always 'larger' than eax, is there extra fluff I am not aware of?
segment .bss
num: resw 1 ;For storing a number, to be read of printed....
nod: resb 1 ;For storing the number of digits....
temp: resb 2
matrix1: resw 200
m: resw 1
n: resw 1
i: resw 1
j: resw 1
small: resb 4 ; temp variable
buff resb 4
segment .data
msg1: db "Enter the number of rows in the matrix : "
msg_size1: equ $-msg1
msg2: db "Enter the elements one by one(row by row) : "
msg_size2: equ $-msg2
msg3: db "Enter the number of columns in the matrix : "
msg_size3: equ $-msg3
msg4: db "The Smallest Number is... : "
msg_size4: equ $-msg4
tab: db 9 ;ASCII for vertical tab
new_line: db 10 ;ASCII for new line
segment .text
global _start
_start:
;; code for reading number of rows and columns, this works fine.
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg_size1
int 80h
;; read in rows
mov ecx, 0
call read_num
mov cx, word[num]
mov word[m], cx
mov eax, 4
mov ebx, 1
mov ecx, msg3
mov edx, msg_size3
int 80h
;; read in columns
mov ecx, 0
call read_num
mov cx, word[num]
mov word[n], cx
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg_size2
int 80h
;; Reading in each element and storing it into the array
mov esi, 0
mov ebx, matrix1
;; init loop
mov word[i], 0
mov word[j], 0
;; Outer loop
i_loop:
mov word[j], 0
;; Inner Loop
j_loop:
;; A function
call read_num
;; Result of that function is now stored int he matrix
mov dx , word[num]
mov word[ebx + 2 * esi], dx
inc esi ;Incrementing array index by one....
inc word[j]
mov cx, word[j]
cmp cx, word[n]
jb j_loop
;; End Inner Loop
inc word[i]
mov cx, word[i]
cmp cx, word[m]
jb i_loop
;; End Outer Loop
;; Now begins the code to find the smallest number
mov eax, [matrix1]
;; Moves first element of Matrix1 into eax
;;; saves eax into small
mov [small], eax
;Loop through the matrix, check each number if its smaller than the first number in the array. AT the end print said number.
;Reading each element of the matrix.(Storing the elements in row major order).......
mov esi, 0
mov edi, matrix1
;; Reinit loop cters
mov word[i], 0
mov word[j], 0
;; Loop
i_loop2:
mov word[j], 0
j_loop2:
;eax will contain the array index and each element is 2 bytes(1 word) long
mov dx, word[edi+2*esi] ;
mov word[num] , dx
cmp eax,[num] ; compares eax and ebx
jle skip ;if eax is SMALLER than ebx, we can safely skip reassignment
;as our current value is already smallest.
mov eax, [num] ; stores new smallest number if the new number was smaller.
mov [small], eax
;; reassignment code is always skipped.
skip:
inc esi
inc word[j]
mov cx, word[j]
cmp cx, word[n]
jb j_loop2
inc word[i]
mov cx, word[i]
cmp cx, word[m]
jb i_loop2
; code to output the smallest number
;; Some ui text.
mov eax, 4
mov ebx, 1
mov ecx, msg4
mov edx, msg_size4
int 80h
mov ecx, 0
;; Now the actual smallest number
mov eax, 4 ; system_write
mov ebx, 1 ; stdout
mov ecx, [small] ; move smallest element to accumulator
add ecx, 48 ; convert to ascii representation
mov [buff], ecx ; move to memory
mov ecx, buff
mov edx, 4 ; size, 4 bytes
int 80h
exit:
mov eax, 1
mov ebx, 0
int 80h
;Function to read a number from console and to store that in num
read_num:
pusha
mov word[num], 0
loop_read:
mov eax, 3
mov ebx, 0
mov ecx, temp
mov edx, 1
int 80h
cmp byte[temp], 10
je end_read
mov ax, word[num]
mov bx, 10
mul bx
mov bl, byte[temp]
sub bl, 30h
mov bh, 0
add ax, bx
mov word[num], ax
jmp loop_read
end_read:
popa
ret

Oh yes, several hours of fidgeting and seconds after this post I figured out exactly why. Turns out yes, the way I declared "num" yes indeed added in extra information. I changed it to resb 4 and it works.
Crabbaskets.

Related

Addition and Subtraction in Nasm

The code just prints out nothing what would I do for the output that will be 150 and 48? I'm practicing nasm
section .data
num1 db 99
num2 db 51
result db 0
section .text
global _start
_start:
; Addition
mov al, [num1]
add al, [num2]
mov [result], al
call display_result
; Subtraction
mov al, [num1]
sub al, [num2]
mov [result], al
call display_result
; Exit program
mov eax, 1
int 0x80
display_result:
; Display result
mov edx, 1
mov ecx, [result]
mov ebx, 1
mov eax, 4
int 0x80
; Display newline
mov edx, 1
mov ecx, 10
mov ebx, 1
mov eax, 4
int 0x80
exit:
mov eax, 1
int 0x80`
I expect for my coding to print the Addition and Subtraction of Num1 and Num2 but it is not printing what would I do for it to print?
See DIV instruction, I think it will best fit your needs. Just divide number by 10 and add the remainder to ASCII '0' value and your result will be one digit from the back of the number you are trying to print. For example: 157 will produce 7 remainder first time, 5 second time and then you'll be left with 1 itself. Hope you get the idea.

Incorrect console output after previous output

Task: output the number in hexadecimal form to the console. After that print some string (let it be "String after num").
The first part is successful, but the second is not.
The input number is stored in memory by the num label.
String is stored in memory by the line label.
String length - lines.
Code:
global _start
section .data
num db 01111110b
temp db 0
line db 10, "String after num", 10
lines equ $-line
section .text
_start:
call write_hex ; write num in hex format
mov eax, 4 ; write "Hello world!"
mov ebx, 1 ;
mov ecx, line ;
mov edx, lines ;
int 80H ;
mov eax, 1 ; exit
xor ebx, ebx
int 80H
write_hex:
mov eax, [num]
mov [temp], eax
shr byte [num], 4
call to_hex_digit
call write_digit
mov eax, [temp]
mov [num], eax
and byte [num], 1111b
call to_hex_digit
call write_digit
ret
to_hex_digit:
add [num], byte '0'
cmp [num], byte '9'
jle end
add [num], byte 7
end: ret
write_digit:
mov eax, 4
mov ebx, 1
mov ecx, num
mov edx, 1
int 80H
ret
Output:
Thanks for any help.
I used an invalid register to store a temporary value. I replaced the register which will work with the temp from eax to al. See Jester's answer.

Adding 2 inputted numbers in Assembly using NASM

I have done my best to explain all of my thought process when adding these two numbers. However, upon running the resulting executable I end up with
"Sum is: j" which is clearly wrong. Additionally, it seems that no matter which inputs I give the sum stays as "j" so there must be something awfully wrong.
I believe this code should work but my understanding is clearly flawed.
Where should I start in fixing this? I just recently began learning assembly.
section .data ;line 1
msg db "Sum is: "
len equ $ - msg
section .bss
num1 resb 1
eol1 resb 1
num2 resb 1
eol2 resb 1
sum resb 2
section .text
global _start
print_int:
mov eax, 4 ;defining routine print_int
mov ebx, 1 ;file descriptor (stdout)
int 0x80 ;system call number (sys_write)
ret ;return back
_start:
;Read and store user input for num1
mov eax, 3
mov ebx, 0
mov ecx, num1
mov edx, 2 ;2 bytes of info
int 80h
mov byte [eol1], 0xA ; value of first end of line
;Read and store user input for num2
mov eax, 3
mov ebx, 0
mov ecx, num2
mov edx, 2 ;2 bytes of info
int 80h
mov byte [eol2], 0xA ;value of 2nd end of line
;Add num1 and num2
mov eax, num1
sub eax, '0' ;this is so that the value in 3 is set to 3 because
;'3' and '0' actually are ASCII values
mov ebx, num2
sub ebx, '0'
add eax, ebx ;Move the sum of 0x3 and 0x4 into eax
add eax, '0' ;Set eax to be the ASCII value for the result of the sum
mov [sum], eax ;Set this ascii value of the sum to sum
mov ecx, msg ;Move msg ('Sum is: ') into eax
mov edx, len ;Move len (length of msh) into edx
call print_int ; call routine print_int above
;load sum to to be printed
mov ecx, sum
mov edx, 2 ;size in bytes of sum
call print_int
mov eax, 1 ;system call number (sys_exit)
xor ebx, ebx
int 0x80 ;line 43
Your program operates on 2 single digit numbers inputted by the user.
mov eax, num1
mov ebx, num2
On NASM, this will move the address of these variables in those registers. What you want is the contents! You need to write the square brackets.
But wait - since the input has only a single byte of information, you should read the data in the byte-sized registers AL and BL.
mov al, [num1]
mov bl, [num2]
All subtractions and additions then will also have to use these smaller sizes.
sub al, '0' ;From character '0'-'9' to number 0-9
sub bl, '0'
add al, bl
add al, '0' ;From number 0-9 to character '0'-'9'
The character in AL is what you want to print. Easiest is to first append the newline 0xA in the AH register and then write AX in the memory.
mov ah, 0xA
mov [sum], ax
All the above is correct whenever the sum of the 2 single digit numbers was less than 10.
Imagine what will happen when you input e.g. numbers 5 and 8 ?
The sum (13) would require 2 characters leaving no room for the extra newline character. The largest sum will come from adding 9 and 9 (18).
Best re-define "sum" as sum resb 3.
Then write the following:
mov al, [num1]
mov bl, [num2]
sub al, '0'
sub bl, '0'
add al, bl
mov edx, 2 ;String length if single digit sum
mov ecx, sum ;Address of sum
cmp al, 10
jb SingleDigit
mov byte [ecx], '1'
inc ecx ;Move to position for the units/newline
inc edx ;String length if double digit sum
sub al, 10 ;Only keep the units
SingleDigit:
add al, '0' ;From number 0-9 to character '0'-'9'
mov ah, 0xA ;Append newline
mov [ecx], ax
mov ecx, sum
call print_int

Getting digit instead of Ascii in nasm assembly intel x86

I'm trying to learn the basics of assembly but can't get across on how to display results stored in memory.
section .data
num1 db 1,2,3,4,5
num2 db 1,2,3,4,5
output: db 'The dot product is "'
outputLen1 : equ $-output
output2: db '" in Hex!', 10
output2Len : equ $-output2
section .bss
dotProd resw 1 ; store dot product in here
section .text
global _start
_start:
mov eax, 0
mov ecx, 5
mov edi, 0
mov esi, 0
looper: mov ax, [edi + num1]
mov dx, [esi + num2]
mul dx
add [dotProd], ax
cmp cx, 1
je printOutput
inc edi
inc esi
dec cx
jmp looper ; go back to looper
printOutput:
mov eax,4 ; The system call for write (sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx, output ;
mov edx, outputLen1 ;
int 80h ; Call the kernel
mov eax, 4
mov ebx, 1
mov ecx, dotProd,
mov edx, 1
int 80h
mov eax, 4
mov ebx, 1
mov ecx, output2,
mov edx, output2Len
int 80h
jmp done
done:
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 80h
What I'm trying to do is get the dot product of the two list of numbers and display it on the screen. However, I keep getting random letters which I believe are hex representations of the real decimal value. How can I convert it to decimal? The current value display is 7, which should is the equivalent ASCII char for 55, which in this case is the dot product of both list of numbers.
esi and edi must be increased such that it points to next element of array.(in this particular example, only one of them is sufficient).
declare mun1 andnum2 as dd, instead of db (see here).
Also, you have to have method for printing number.(see this and this).
Below is a complete code which uses printf.
;file_name:test.asm
;assemble and link with:
;nasm -f elf test.asm && gcc -m32 -o test test.o
extern printf
%macro push_reg 0
push eax
push ebx
push ecx
push edx
%endmacro
%macro pop_reg 0
pop edx
pop ecx
pop ebx
pop eax
%endmacro
section .data
num1: dd 1,2,3,4,5
num2: dd 1,2,3,4,5
msg: db "Dot product is %d",10,0
section .bss
dotProd resd 1 ; store dot product in here
section .text
global main
main:
mov eax, 0
mov ecx, 5
mov edx, 0
mov esi, 0
mov dword[dotProd], 0h
looper: mov eax, dword[esi + num1]
mov edx, dword[esi + num2]
mul edx
add [dotProd], eax
cmp cx, 1
je printOutput
add esi,4
dec cx
jmp looper ; go back to looper
printOutput:
push_reg
push dword[dotProd]
push dword msg
call printf
add esp,8
pop_reg
jmp done
done:
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 80h

Linux nasm assembly append character/s to a string

On NASM in Arch Linux, how can I append the character zero ('0') to a 32 bit variable? My reason for wanting to do this is so that I can output the number 10 by setting a single-digit input to 1 and appending a zero. I need to figure out how to append the zero.
The desirable situation:
Please enter a number: 9
10
Using this method, I want to be able to do this:
Please enter a number: 9999999
10000000
How can I do this?
Thanks in advance,
RileyH
Well, as Bo says... but I was bored. You seem resistant to doing this the easy way (convert your input to a number, add 1, and convert it back to text) so I tried it using characters. This is what I came up with. It's horrid, but "seems to work".
; enter a number and add 1 - the hard way!
; nasm -f elf32 myprog.asm
; ld -o myprog myprog.o -melf_i386
global _start
; you may have these in an ".inc" file
sys_exit equ 1
sys_read equ 3
sys_write equ 4
stdin equ 0
stdout equ 1
stderr equ 2
LF equ 10
section .data
prompt db "Enter a number - not more than 10 digits - no nondigits.", LF
prompt_size equ $ - prompt
errmsg db "Idiot human! Follow instructions next time!", LF
errmsg_size equ $ - errmsg
section .bss
buffer resb 16
fakecarry resb 1
section .text
_start:
nop
mov eax, sys_write
mov ebx, stdout
mov ecx, prompt
mov edx, prompt_size
int 80h
mov eax, sys_read
mov ebx, stdin
mov ecx, buffer + 1 ; leave a space for an extra digit in front
mov edx, 11
int 80h
cmp byte [buffer + 1 + eax - 1], LF
jz goodinput
; pesky user has tried to overflow us!
; flush the buffer, yell at him, and kick him out!
sub esp, 4 ; temporary "buffer"
flush:
mov eax, sys_read
; ebx still okay
mov ecx, esp ; buffer is on the stack
mov edx, 1
int 80h
cmp byte [ecx], LF
jnz flush
add esp, 4 ; "free" our "buffer"
jmp errexit
goodinput:
lea esi, [buffer + eax - 1] ; end of input characters
mov byte [fakecarry], 1 ; only because we want to add 1
xor edx, edx ; count length as we go
next:
; check for valid decimal digit
mov al, [esi]
cmp al, '0'
jb errexit
cmp al, '9'
ja errexit
add al, [fakecarry] ; from previous digit, or first... to add 1
mov byte [fakecarry], 0 ; reset it for next time
cmp al, '9' ; still good digit?
jna nocarry
; fake a "carry" for next digit
mov byte [fakecarry], 1
mov al, '0'
cmp esi, buffer + 1
jnz nocarry
; if first digit entered, we're done
; save last digit and add one ('1') into the space we left
mov [esi], al
inc edx
dec esi
mov byte [esi], '1'
inc edx
dec esi
jmp done
nocarry:
mov [esi], al
inc edx
dec esi
cmp esi, buffer
jnz next
done:
inc edx
inc edx
mov ecx, esi ; should be either buffer + 1, or buffer
mov ebx, stdout
mov eax, sys_write
int 80h
xor eax, eax ; claim "no error"
exit:
mov ebx, eax
mov eax, sys_exit
int 80h
errexit:
mov edx, errmsg_size
mov ecx, errmsg
mov ebx, stderr
mov eax, sys_write
int 80h
mov ebx, -1
jmp exit
;-----------------------------
Is that what you had in mind?

Resources