ARM汇编语言概念技术咨询:基于小写转大写代码的疑问
Hey there! Let's walk through each of your questions about this ARM lowercase-to-uppercase assembly code clearly—ARM syscall conventions and register usage can feel opaque at first, so breaking it down helps a lot.
1. How do I map registers to syscalls and know which parameters to pass?
On ARM Linux (the environment this code targets, since it uses SWI 0 to trigger syscalls), the convention is straightforward:
R7holds the syscall number: each kernel function (like read, write, exit) has a unique number assigned to it. For example:#3=read(read input from a file descriptor)#4=write(write output to a file descriptor)#1=exit(terminate the process)
R0-R3are used for syscall parameters, in order. For example:- For
read(R7=3):R0= file descriptor (0 = standard input/stdin)R1= pointer to the buffer where input will be storedR2= number of bytes to read
- For
write(R7=4):R0= file descriptor (1 = standard output/stdout)R1= pointer to the buffer with data to writeR2= number of bytes to write
These conventions are part of the ARM Linux ABI (Application Binary Interface)—you can look up the full list of syscall numbers and their required parameters for your specific ARM architecture.
- For
2. What happens to R0's old value after reuse? Does the program run line-by-line? Where is the keyboard input stored?
- Program execution order: Yes, the program runs sequentially line-by-line unless a branch instruction (like
B,BL, or conditional branches) changes the flow. In this code, there are no branches that jump away from the linear flow, so it runs from_startthrough toend. - R0's old value: Registers are volatile—when you assign a new value to a register (like
LDR R0, [R1]on line 13), it completely overwrites whatever was in R0 before. After thereadsyscall (line 6), R0 held the number of bytes successfully read (which should be 1 here, since we asked to read 1 byte). That value is lost once we load the character from memory into R0. - Input storage: The
readsyscall stores the input character in the memory location pointed to byR1—which, in line 5, we set to=character(the address of thecharactervariable in the.datasection). So your typed character lives in that.asciibuffer after thereadcompletes.
3. What happens to the memory address stored in R0 before the write syscall?
Wait, let's clarify the code flow here:
- Line 13:
LDR R0, [R1]loads the lowercase character fromcharacterinto R0. - Line 14:
BIC R0, R0, #32clears the 6th bit (value 32) of R0, converting the ASCII lowercase letter to uppercase (since lowercase ASCII letters are exactly 32 higher than their uppercase counterparts). - Line 15:
STR R0, [R1]stores this converted uppercase character back into thecharactermemory location. - Then, in line 19:
MOV R0, #1overwrites R0 with the value 1 (the file descriptor for stdout). The previous value in R0 (the uppercase character) is completely lost—since we didn't save it to memory or another register, it's gone forever. Registers don't retain old values once you assign new ones.
4. Why do some labels use SWI 0 but _uppercase doesn't?
SWI 0 is the instruction that triggers a system call—it tells the CPU to switch from user-mode code (your assembly) to kernel-mode code (the Linux kernel handling I/O, process termination, etc.).
- Labels like
_start(read),_write(write), andend(exit) all rely on kernel services, so they needSWI 0to ask the kernel to do the work. - The
_uppercaselabel is just doing user-mode operations: loading a value from memory, modifying it with a bitwise instruction (BIC), and storing it back. These are all operations the CPU can do directly without involving the kernel, so noSWI 0is needed here.
5. Why do we need the exit syscall before SWI 0 to terminate the program?
Line 24: MOV R7, #1 sets the syscall number to exit (which is 1 for ARM Linux). The subsequent SWI 0 triggers the kernel to execute the exit syscall.
- This is necessary because when your program finishes, you need to tell the kernel to clean up all the resources associated with your process (like memory, file descriptors, etc.). If you don't explicitly call
exit, the kernel might still clean up eventually, but it's not reliable—your process could hang as a zombie, or cause unexpected behavior. - The
SWI 0is required to actually invoke the exit syscall; just setting R7 to 1 doesn't do anything on its own—you need to trigger the kernel switch withSWI 0.
内容的提问来源于stack exchange,提问作者southwickIO

