Я работаю над кодом на языке ассемблера, который вычисляет снегопад. Он запрашивает у пользователя количество (в дюймах) снега, которое упало в цикле do-while, пока пользователь не войдет в 0, который прерывает цикл. Также в цикле суммы суммируются друг с другом. После ввода 0 программа должна печатать общее количество снегопада в футах и дюймах.Несколько вопросов, касающихся функций в языке ассемблера IA32
Моя программа имеет 3 функции, которые были предоставлены мне: printStr, readUInt и printUInt вместе с моей основной. Я понимаю, как работают printStr и readUInt, но я не понимаю, как работает printUInt, поэтому я надеялся, что кто-то мне это объяснит.
Кроме того, когда мне приходится печатать «Общее количество снегопада: # футов и # дюймов», у меня возникли проблемы с выяснением того, как я напечатаю два числа в строке, некоторые советы по этому вопросу также будут полезны.
Я работаю над этим часами, и меня бы здесь не было, если бы я не был полностью в тупике.
printStr (ЭОД = адрес нуля строки для печати)
printStr:
pushq %rbp
movq %rsp,%rbp
subq $24,%rsp
movl %ebx, -4(%rbp)
movl %edi, %ecx # Copy the "Start"
printStr_loop:
movb (%ecx),%al
cmpb $0,%al
jz printStr_end
# Syscall to print a character
movl $4, %eax # Print (write) syscall
movl $1, %ebx # Screen (file)
# movl $Hello, %ecx
movl $1, %edx # One character
int $0x80
addl $1, %ecx
jmp printStr_loop
printStr_end:
movl $-1,%eax
movl $-1,%ecx
movl $-1,%edx
movl -4(%rbp), %ebx
leave
ret
.data
printUIntBuffer: .asciz " "
printUIntBufferEnd=.-2
.text
printUInt (ЭОД = целое число без знака для печати):
printUInt:
pushq %rbp
movq %rsp,%rbp
subq $24,%rsp
movl %ebx, -4(%rbp)
movl %edi, -8(%rbp)
movl $10, -12(%rbp) # Constant 10 used for division/modulus
movl %edi, %eax # eax = digits left to convert
movl $printUIntBufferEnd,%ecx # %ecx is the insert point
# Convert each digit into a characters
printUInt_loop:
movl $0, %edx # Reset high portion for division
divl -12(%rbp) # Divide edx:eax by 10; edx=Remainder/eax = quotient
addb $'0',%dl
movb %dl,0(%ecx)
subl $1,%ecx
testl %eax,%eax
jnz printUInt_loop
# Done with loop, print the buffer
movl %ecx,%edi
addl $1,%edi
call printStr
printUInt_end:
movl $-1,%eax
movl $-1,%ecx
movl $-1,%edx
movl -8(%rbp), %edi
movl -4(%rbp), %ebx
leave
ret
.data
readUInt_bufferStart = .
readUInt_buffer: .ascii " "
.text
readUInt (возвращает считанный без знака Int в % EAX)
readUInt:
pushq %rbp # Save the old rpb
movq %rsp, %rbp # Setup this frames start
movl %ebx,-4(%rbp)
movl $0,%eax # initialize accumulator
readUInt_next_char:
# Read a character
movl %eax,-8(%rbp)
movl $3, %eax # issue a read
movl $1,%ebx # File descriptor 1 (stdin)
movl $1,%edx # sizet = 1 character
movl $readUInt_bufferStart,%ecx
int $0x80 # Syscall
movl -8(%rbp),%eax
# Get the character
movb readUInt_bufferStart,%bl
cmpb $'0',%bl
jb readUInt_end
cmpb $'9',%bl
ja readUInt_end
movl $10,%edx
mul %edx
subb $'0',%bl
addl %ebx,%eax
jmp readUInt_next_char
readUInt_end:
movl $-1,%ecx
movl $-1,%edx
movl -4(%rbp),%ebx
leave
ret
данных для основной:
.data
AskSF: .asciz "How many inches of snow to add (0 when done): "
TotalSF: .asciz "Total snowfall: %d feet and inches "
.text
основные:
do_while:
movl $AskSF, %edi
call printStr #asking for amount of snowfall
call readUInt
addl %eax,%edx #adding amounts of snowfall together
movl %eax,%ecx #moving entered amount to compare with 0
cmpl $0,%ecx # checking if amount is 0 to see if loop should exit
jne do_while
#below here I was just experimenting looking for solutions
movl $TotalSF,%edi
call printStr
movl %edx,%edi
call printUInt
Ничего себе, не то, что я ожидал. Спасибо тебе, Тони! – denholm