英文:
How to use _scanf in Apple Silicon (aarch64 macos) assembly to read in user input?
问题
I'm new to assembly programming, but I've been figuring a lot out by googling and trial and error. I'm trying to write a simple program that prompts the user to enter a number (with _printf), then reads in and saves that number (_scanf), then prints out a message using the stored number (_printf).
I was able to get the _printf code to work under aarch64 (Apple Silicon) assembly, but no matter what I do, I cannot seem to get _scanf to work. I have looked through the ARM Developer docs, looked at the HelloSilicon github page, and googled for hours, and I cannot come up with anything that works.
In my code (included below), if I comment out the "read_from_keyboard" branch in the following code, the printf functions work just fine. But when I include the "read_from_keyboard" code, I get a "Segmentation fault: 11" error.
Where is my mistake?
.global main
.align 4
main:
// PRINT MESSAGE
ADRP X0, message@PAGE
ADD X0, X0, message@PAGEOFF
BL _printf
// BL read_from_keyboad
// READ NUMBER FROM DATA AND MOVE TO STACK FOR PRINTING
ADRP X10, num@PAGE
ADD X10, X10, num@PAGEOFF
LDR X1, [X10]
STR X1, [SP, #-16]!
// LOAD THE PRINTF FORMATTED MESSAGE
ADRP X0, output_format@PAGE
ADD X0, X0, output_format@PAGEOFF
end:
BL _printf
mov X16, #1
svc 0
read_from_keyboard:
ADRP X0, input_format@PAGE
ADD X0, X0, input_format@PAGEOFF
ADRP X11, num@PAGE
ADD X11, X11, num@PAGEOFF
BL _scanf
ret
.data
.balign 4
message: .asciz "What is your favorite number?\n"
.balign 4
num: .word 32
.balign 4
input_format: .asciz "%d"
.balign 4
output_format: .asciz "Your favorite number is %d \n"
(Note: Code sections are provided as requested. Please note that this code may not run properly due to potential issues with the assembly code itself or system-specific configurations.)
英文:
I'm new to assembly programming, but I've been figuring a lot out by googling and trial and error. I'm trying to write a simple program that prompts the user to enter a number (with _printf), then reads in and saves that number (_scanf), then prints out a message using the stored number (_printf).
I was able to get the _printf code to work under aarch64 (Apple Silicon) assembly, but no matter what I do, I cannot seem to get _scanf to work. I have looked through the ARM Developer docs, looked at the HelloSilicon github page, and googled for hours, and I cannot come up with anything that works.
In my code (included below), if I comment out the "read_from_keyboard" branch in the following code, the printf functions work just fine. But when I include the "read_from_keyboard" code, I get a "Segmentation fault: 11" error.
Where is my mistake?
.global main
.align 4
main:
// PRINT MESSAGE
ADRP X0, message@PAGE
ADD X0, X0, message@PAGEOFF
BL _printf
// BL read_from_keyboad
// READ NUMBER FROM DATA AND MOVE TO STACK FOR PRINTING
ADRP X10, num@PAGE
ADD X10, X10, num@PAGEOFF
LDR X1, [X10]
STR X1, [SP, #-16]!
// LOAD THE PRINTF FORMATTED MESSAGE
ADRP X0, output_format@PAGE
ADD X0, X0, output_format@PAGEOFF
end:
BL _printf
mov X16, #1
svc 0
read_from_keyboard:
ADRP X0, input_format@PAGE
ADD X0, X0, input_format@PAGEOFF
ADRP X11, num@PAGE
ADD X11, X11, num@PAGEOFF
BL _scanf
ret
.data
.balign 4
message: .asciz "What is your favorite number?\n"
.balign 4
num: .word 32
.balign 4
input_format: .asciz "%d"
.balign 4
output_format: .asciz "Your favorite number is %d \n"
答案1
得分: 0
在对 _printf
的调用中,你的可变参数位于 [sp]
。在对 _scanf
的调用中,你将它放在了 x11
中。为什么这样做?只需执行与 _printf
中相同的操作 str xN, [sp, #-16]!
,这将修复你的段错误。
另外,你还需要为 read_from_keyboard
创建一个堆栈帧。bl _scanf
会破坏 x30
,因此接下来的 ret
会陷入无限循环。
修复这两个问题,你的代码就可以正常工作:
.global _main
.align 4
_main:
// 打印消息
ADRP X0, message@PAGE
ADD X0, X0, message@PAGEOFF
BL _printf
BL read_from_keyboard
// 从数据中读取数字并移到堆栈以进行打印
ADRP X10, num@PAGE
ADD X10, X10, num@PAGEOFF
LDR X1, [X10]
STR X1, [SP, #-16]!
// 载入 printf 格式化消息
ADRP X0, output_format@PAGE
ADD X0, X0, output_format@PAGEOFF
end:
BL _printf
mov X16, #1
svc 0
read_from_keyboard:
STP X29, X30, [SP, #-16]!
ADRP X0, input_format@PAGE
ADD X0, X0, input_format@PAGEOFF
ADRP X11, num@PAGE
ADD X11, X11, num@PAGEOFF
STR X11, [SP, #-16]!
BL _scanf
ADD SP, SP, #16
LDP X29, X30, [SP], #16
ret
.data
.balign 4
message: .asciz "What is your favorite number?\n"
.balign 4
num: .word 32
.balign 4
input_format: .asciz "%d"
.balign 4
output_format: .asciz "Your favorite number is %d \n"
请注意,我只翻译了代码中的注释和字符串部分,而没有进行其他更改。
英文:
On the call to _printf
, your variadic arg is in [sp]
. On the call to _scanf
, you put it in x11
. Why? Just do the same str xN, [sp, #-16]!
that you do on _printf
, that'll fix your segfault.
In addition though, you also need a stack frame for read_from_keyboard
. The bl _scanf
clobbers x30
, so the following ret
would just get stuck in an infinite loop.
Fix these two issues and your code works:
.global _main
.align 4
_main:
// PRINT MESSAGE
ADRP X0, message@PAGE
ADD X0, X0, message@PAGEOFF
BL _printf
BL read_from_keyboard
// READ NUMBER FROM DATA AND MOVE TO STACK FOR PRINTING
ADRP X10, num@PAGE
ADD X10, X10, num@PAGEOFF
LDR X1, [X10]
STR X1, [SP, #-16]!
// LOAD THE PRINTF FORMATTED MESSAGE
ADRP X0, output_format@PAGE
ADD X0, X0, output_format@PAGEOFF
end:
BL _printf
mov X16, #1
svc 0
read_from_keyboard:
STP X29, X30, [SP, #-16]!
ADRP X0, input_format@PAGE
ADD X0, X0, input_format@PAGEOFF
ADRP X11, num@PAGE
ADD X11, X11, num@PAGEOFF
STR X11, [SP, #-16]!
BL _scanf
ADD SP, SP, #16
LDP X29, X30, [SP], #16
ret
.data
.balign 4
message: .asciz "What is your favorite number?\n"
.balign 4
num: .word 32
.balign 4
input_format: .asciz "%d"
.balign 4
output_format: .asciz "Your favorite number is %d \n"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论