首页 > 解决方案 > ARM 程序集堆栈值不移动

问题描述

我正在尝试在 ARM Assembly 中构建一个基本的 4 函数计算器。我们必须使用 Push 和 Pop,这 4 个函数中的每一个都必须是自己的子程序。

由于某种原因,我无法将值传递给子例程。教授说我们不需要使用堆栈帧或帧指针,我想这很好,但我不知道为什么这不起作用。我在正确的地方使用了 PUSH 命令吗?我是否只需要推动 LR,如果是,我应该如何以及在哪里放置它?

如果格式混乱,也很抱歉。我不知道如何在 Stack Overflow 中做任何事情。

.equ READERROR, 0 @Used to check for scanf read error.
.global main @ Have to use main because of C library uses. 

main:

@*******************
begin:
@*******************

@ Welcome message.

ldr r0, =strInputPrompt  @ Put the address of my string into the first parameter
bl  printf               @ Call the C printf to display input prompt.

ldr r0, =inputPrompt1    @ Put the address of my string into the first parameter
bl  printf               @ Call the C printf to display input prompt.

ldr r0, =numInputPattern @ Setup to read in one number.
ldr r1, =intInput        @ load r1 with the address of where theinput value will be stored.

bl scanf            @ scan the keyboard
cmp r0, #READERROR       @ Check for a read error.
beq readerror            @ If there was a read error go handle it. 

ldr r3, =intInput       @ load intInput into r3
ldr r3, [r3]            @ Read the contents of intInput and store in r3
mov r2, #-1         @ load -1 into r2
cmp r3, r2          @ is the value entered less than or equal to -1?
ble invalidnums     @ if yes, print invalid message
ldr r0, =inputPrompt2    @ Put the address of my string into the first parameter
bl  printf               @ Call the C printf to display input prompt.
ldr r0, =numInputPattern @ Setup to read in one number.
ldr r1, =intInput2       @ load r1 with the address of where theinput value will be stored.

bl scanf            @ scan the keyboard
cmp r0, #READERROR       @ Check for a read error.
ldr r4, =intInput        @ load intInput into r4 
ldr r4, [r4]             @ Read the contents of intInput and store in r4
mov r3, #-1         @ load -1 into r2
cmp r4, r3          @ is the value entered less than or equal to -1?
ble invalidnums     @ if yes, print invalid message

@blt again         @ if invalid return value, ask for another attempt
@mov r1, r0
@ldr r0, =answer
@bl printf         @ print the answer
@b again           @ ask another attempt

@*******************
get_op:
@*******************

ldr r0, =inputPrompt3    @ Put the address of my string into the first parameter
bl  printf               @ Call the C printf to display input prompt.

ldr r0, =charInputPattern @ Setup to read in one number.
ldr r1, =charInput        @ load r1 with the address of where theinput value will be stored.

bl scanf            @ scan the keyboard
cmp r0, #READERROR       @ Check for a read error.
ldr r5, =charInput       @ load charInput into r5 
ldr r5, [r5]             @ Read the contents of charInput and store in r5

push {r3,r4}

cmp r5, #'+'        @ did user enter +?
beq addTest             @ if yes, go to addTest

cmp r5, #'-'        @ did user enter -?
beq subTest             @ if yes, go to subTest

cmp r5, #'*'            @ did user enter *?
beq multTest        @ if yes, go to multTest

cmp r5, #'/'            @ did user enter /?
beq divTest             @ if yes, go to divTest

b begin             @ back to beginning of program

@*******************
addTest:
@*******************
ldr r0, =addOpt        @ Put the address of my string into the first parameter
bl  printf              @ Call the C printf to display input prompt. 

bl addCalc
pop {r0}
mov r1, r0
ldr r0, =answer
bl printf

@*******************
subTest:
@*******************
ldr r0, =subOpt        @ Put the address of my string into the first parameter
bl  printf              @ Call the C printf to display input prompt. 

bl subCalc
pop {r0}
mov r1, r0
ldr r0, =answer
bl printf
@*******************
multTest:
@*******************
ldr r0, =multOpt       @ Put the address of my string into the first parameter
bl  printf              @ Call the C printf to display input prompt. 

bl multCalc
pop {r0}

@*******************
divTest:
@*******************
ldr r0, =divOpt        @ Put the address of my string into the first parameter
bl  printf              @ Call the C printf to display input prompt. 

bl divCalc
pop {r0}

@***********
addCalc:
@***********

pop {r5,r6}
add r6, r5, r6

@cmp r6, #0            @ test if upper word is non-zero (for overflow)
@vs overflow
@movgt r7, #-1     @ if overflow, load -1 as a result
@asrle r7, #1      @ if not, divide by 2
@blgt overflow     @ if overflow, print overflow
@mov r0, r7

push {r6}
bx lr          @ return

@***********
subCalc:
@***********

pop {r5,r6}
subs r6, r5, r6        @ subtract r5-r6 and store in r6
@cmp r6, #0            @ test if upper word is non-zero (for overflow)
@vs overflow
@movgt r7, #-1     @ if overflow, load -1 as a result
@asrle r7, #1      @ if not, divide by 2
@blgt overflow     @ if overflow, print overflow
@mov r0, r7

push {r6}          @ return
bx lr

@***********
multCalc:
@***********

mov r6, #0
umull r7, r6, r4, r5    @ 64-bit multiplication
@cmp r6, #0            @ test if upper word is non-zero (for overflow)
@vs overflow
@movgt r7, #-1     @ if overflow, load -1 as a result
@asrle r7, #1      @ if not, divide by 2
@blgt overflow     @ if overflow, print overflow
mov r0, r7

push {r6}          
bx lr          @ return

@***********
divCalc:
@***********


mov r6, #0
bl divLoop
@cmp r6, #0            @ test if upper word is non-zero (for overflow)
@vs overflow
@movgt r7, #-1     @ if overflow, load -1 as a result
@asrle r7, #1      @ if not, divide by 2
@blgt overflow     @ if overflow, print overflow
@mov r0, r7

push {r6}          
bx lr          @ return

@***********
divLoop:
@***********

subs r4, r4, r5        @ r4-r5 and store in r4. this will be remainder
adds r7, r7, #1        @ increment by 1. this is how many times r4 has been divided
cmp r4, r5         @ if r4 < r5 return to divCalc
bx lr

@***********
overflow:
@***********
push {lr}   
push {fp}   
mov fp, sp         @ create stack frame
ldr r0, =overstr       @ load overflow string
bl printf          @ print overflow string
pop {fp}           @ restore stack frame
pop {pc}           @ return

@***********
returnInput:
@***********
@ reset stack
add sp, #4         @ restore stack
pop {fp}           @ restore frame
pop {pc}           @ return

@***********
again:
@***********
ldr r0, =againstr
bl printf          @ print againstr
sub sp, #1         @ allocate space for one char
mov r1, sp
ldr r0, =charInputPattern
bl scanf           @ scan the keyboard
mov r0, #0
ldrsb r0, [sp], #4     @ load char and restore stack
cmp r0, #'y'       @ compare to 'y'
beq begin          @ if y, go back to the beginning
cmp r0, #'n'       @ compare to 'n'
beq myexit         @ if n, exit the program
b again            @ else, try again

@***********
invalidnums:
@***********
ldr r1, [fp, #8]
mov r0, #-1
str r0, [r1] @set the inputted value to -1
sub sp, #100       @ allocate space for a 100-character string
ldr r0, =charInputPattern
mov r1, sp
bl scanf           @ scan the keyboard
add sp, #100       @ restore stack

@*******************
myexit:
@*******************
@ End of my code. Force the exit and return control to OS

mov r7, #0x01 @SVC call to exit
svc 0         @Make the system call. 

@***********
readerror:
@***********
@ Got a read error from the scanf routine. Clear out the input buffer then
@ branch back for the user to enter a value. 
@ Since an invalid entry was made we now have to clear out the input buffer by
@ reading with this format %[^\n] which will read the buffer until the user 
@ presses the CR. 

ldr r0, =strInputPattern
ldr r1, =strInputError   @ Put address into r1 for read.
bl scanf                 @ scan the keyboard.
@  Not going to do anything with the input. This just cleans up the input buffer.  
@  The input buffer should now be clear so get another input.

b again



.data

@ Declare the strings and data needed

.balign 4
strInputPrompt: .asciz "Hello. Enter 2 non-negative integers and an operation (+, -, *, or /) and I 
will calculate the answer. \n"

.balign 4
inputPrompt1: .asciz "Enter first non-negative integer: \n "

.balign 4
inputPrompt2: .asciz "Enter second non-negative integer: \n "

.balign 4
inputPrompt3: .asciz "Enter the operation (+, -, *, or /): \n "

.balign 4
addOpt: .asciz "Addition \n "

.balign 4
subOpt: .asciz "Subtraction \n "

.balign 4
multOpt: .asciz "Multiplication \n "

.balign 4
divOpt: .asciz "Division \n "

.balign 4
answer: .asciz "The answer is: \n"

.balign 4
overstr: .asciz "Overflow \n"

.balign 4
againstr: .asciz "Try another calculation? \n"

.balign 4
nl: .asciz "\n"

.balign 4
invalidStr: .asciz "Invalid input, try again \n"

@ Format pattern for scanf call.

.balign 4
numInputPattern: .asciz "%d"  @ integer format for read. 

.balign 4
charInputPattern: .asciz "%s"  @ character format for read.

.balign 4
 intInput: .word 0   @ Location used to store the user input. 

.balign 4
intInput2: .word 0   @ Location used to store the user input. 

.balign 4
charInput: .word 0   @ Location used to store the user input. 

.balign 4
strInputPattern: .asciz "%[^\n]" @ Used to clear the input buffer for invalid input. 

.balign 4
strInputError: .skip 100*4  @ User to clear the input buffer for invalid input. 


@ Let the assembler know these are the C library functions. 

.global printf

.global scanf

@end of code and end of file. Leave a blank line after this.
`

标签: assemblyarmstack

解决方案


尝试使用STMDB指令而不是 PUSHSTMDB代表

每次传输前存储多个寄存器递减地址。(取自 RE 为初学者)

这是降价指南


推荐阅读