I'm trying to write a program in x86 assembly that takes integer input until a 0 is entered, at which point it prints the sum of all of the integers entered, as well as the minimum value among them. I've written the same program in MIPS assembly before, but am running into an error in the x86 version where the sum does not seem to be incrementing at the add command. How can I get it to work? Should I use registers directly instead? I've included the MIPS program and my attempt in x86, which does not have the minimum value part yet.
MIPS program (Can run it using MARS: http://courses.missouristate.edu/kenvollmar/mars/):
#Sum and minimum finder; enter 0 to exit
.data
prompt: .asciiz "Input any integer: "
reply1: .asciiz "The sum of all the integers is "
reply2: .asciiz "The minimum value among the integers is "
period: .asciiz "."
newline: .asciiz "\n"
.text
#Register Usage:
# $t0 = current integer input from user
# $t1 = input sum
# $t2 = lowest value so far
# $t3 = minimum value checker bit
# $t4 = loop counter
#Get integer inputs
li $t0 1 #"Initialize" $t0 to 1 to avoid exiting the loop straight away
li $t4 0 #Set the loop counter to 0
loop1: #Begin loop1
beqz $t0 exit1 #Exit loop if integer input is equal to zero
li $v0 4 #Print prompt1
la $a0 prompt
syscall
li $v0 5 #Take user input for prompt
syscall
move $t0 $v0 #Move user input from $v0 to $t0
add $t1 $t0 $t1 #Add integer to input sum
bgt $t4 $zero exit4 #For the first input only, set $t2 to $t0 without any comparisons
add $t2 $t0 $zero
exit4:
ble $t4 $zero exit3 #For all other subsequent inputs, compare the input in $t0 to the current min value in $t2
beqz $t0 exit2 #Do not do this if $t0 is equal to 0
slt $t3 $t2 $t0 #Implement low water mark algorithm, and check if $t2 < $t0
beq $t3 1 statusquo #If $t2 < $t0, then go to statusquo
add $t2 $t0 $zero #If $t0 is less than the current value in $t2, then the status quo is not kept, and the value in $t2 is replaced by the one in $t0
statusquo:
exit2:
exit3:
addi $t4 $t4 1 #Increment first loop counter by one
j loop1 #Repeat loop1
exit1: #Exit loop1
#Print blank space
li $v0 4 #Place a gap between the input and the output
la $a0 newline
syscall
#Print integer input sum
li $v0 4 #Print reply context
la $a0 reply1
syscall
li $v0 1 #Print sum
move $a0 $t1
syscall
li $v0 4 #Print period to end sentence
la $a0 period
syscall
#Print blank space
li $v0 4 #Place a newline here
la $a0 newline
syscall
#Print minimum value
li $v0 4 #Print reply context
la $a0 reply2
syscall
li $v0 1 #Print min value
move $a0 $t2
syscall
li $v0 4 #Print period to end sentence
la $a0 period
syscall
x86 attempt (Using Irvine library: https://asmirvine.com/):
;This program outputs the sum and minimum of the integers entered, enter 0 to quit.
include \irvine\irvine32.inc
includelib \irvine\irvine32.lib
.data
prompt byte "Input any integer: ",0
space byte " ",0
reply1 byte "The sum of all the integers entered is ",0
reply2 byte "The minimum value among the integers entered is ",0
period byte ".",0
newline byte "\n",0 ;?
num dword ?
sum dword ?
min dword ?
minflag dword ?
loopinc dword ?
.code
main proc
mov num, 1 ;initialize num to 1 to avoid exiting the loop right away
mov loopinc, 0
loop1:
test eax, eax
je exit1
mov edx, offset prompt ;print prompt to console
call writestring
call readint ;take num input
mov num, eax ;move input to num variable
add sum, eax ;add input to sum
add loopinc, 1
loop loop1
exit1:
call crlf ;insert newline
mov edx, offset reply1 ;print reply
call writestring
mov edx, sum ;print sum
call writedec
mov edx, offset period ;print period
call writestring
exit
main endp
end main
You're using WriteDec
incorrectly. It expects the input parameter in EAX
, not EDX
.
See the documentation: https://csc.csudh.edu/mmccullough/asm/help/source/irvinelib/writedec.htm