Is __mmap_switched_data prepared for init_task()? - linux

I was reading the arch/arm/kernel/head.S and I found some code in the __mmap_switch as following:
adr r3, __mmap_switched_data
ldmia r3!, {r4, r5, r6, r7}
cmp r4, r5 # Copy data segment if needed
1: cmpne r5, r6
ldrne fp, [r4], #4
strne fp, [r5], #4
bne 1b
mov fp, #0 # Clear BSS (and zero fp)
1: cmp r6, r7
strcc fp, [r6],#4
bcc 1b
The annotation shows that these operations work for a task(or a thread).And I got the __mmap_switch_data:
__mmap_switched_data:
.long __data_loc # r4
.long _sdata # r5
.long __bss_start # r6
.long _end # r7
.long processor_id # r4
.long __machine_arch_type # r5
.long __atags_pointer # r6
#ifdef CONFIG_CPU_CP15
.long cr_alignment # r7
#else
.long 0 # r7
#endif
.long init_thread_union + THREAD_START_SP # sp
.size __mmap_switched_data, . - __mmap_switched_data
__FINIT
.text
I know the init_thread_union is related with init_task().So are these operations allocation space for the init_task() by a static way as the memory subsystem hasn't been initialized?If it is,how can init_task() get these information?

Related

I get a wrong result if I copy the return value of a function to another register instead of r1, why?

I am trying to print do_something's return value that is stored in r0. After bl do_something statement, if a copy r0 in r1 the output is correct (8). But if a copy r0 in r2, the output is incorrect, why?
.global main
.extern abs
.extern printf
.text
output_str:
.ascii "The answer is %d\n\0"
.align 4
diffofsums:
push {r4, r5, lr}
add r4, r0, r1 ;r4 = f - g
add r5, r2, r3 ;r5 = h - i
sub r0, r4, r5 ;r0 = result = r4 - r5
pop {r4, r5, pc}
bx lr
main:
push {ip, lr}
mov r0, #2
mov r1, #3
mov r2, #4
mov r3, #5
bl diffofsums
mov r2, r0 ;incorrect output! (correct output when I write mov r1, r0)
ldr r0, =output_str
bl printf
mov r0, #0
pop {ip, pc}
Maybe it's a printf problem? I don't quite understand how printing works in ARM Assembly.

ARM Assembly loading string produces weird terminal output

I am trying to space out my string by replacing each character with a space string combined with an underscore string to create _ _ _ _.
However, I get a weird output:
If I load 1 character e.g ldr r1, = '_'
it works however I get _____ and I am trying to get _ _ _ _ _. What is the best way to do this?
NOTE: I do not know C and I am new to ARM.
My function:
sub r3, r0, #1 #has the length
ldr r0, = buffer #has the word
mov r5, #0 #start of increment
mov r6, r0 #copies word to r6
loop:
ldr r1, =spaceChar
strb r1, [r6, r5]
add r5, r5, #1
cmp r3, r5
bne loop
mov r1,r6
ldr r0, = HiddenWord
bl printf
pop {r4,lr}
bx lr
.data
HiddenWord:
.asciz "Word: %s"
spaceChar:
.asciz " _"
buffer:
.space 100
Since you already statically allocate the buffer the simplest solution is to preset it with " _" using your assembler and just put the terminating zero in the right place. I don't think you mentioned which assembler you use, the following works in gnu assembler:
ldr r0, =buffer-1
mov r1, #0
strb r1, [r0, r3, lsl #1]
ldr r0, =HiddenWord
ldr r1, =buffer
bl printf
pop {r4,lr}
bx lr
.data
HiddenWord:
.asciz "Word: %s\n"
buffer:
.rept 50
.ascii "_ "
.endr
If you want to fill the buffer programmatically, that could look like:
ldr r0, =buffer #has the word
ldr r1, =0x205f # underscore + space
loop:
strh r1, [r0], #2
subs r3, r3, #1
bne loop
mov r1, #0 # replace final
strb r1, [r0, #-1] # space with zero

Print Newline for Armv7 assembly program

I'm working on this armv7 assembly program that finds the greatest common divisor(gcd) of two integers. Everything is working fine except for the newline function. When i assemble and run the program, it doesn't print any newlines, just the integers in one line. Any suggestions on how i can fix that?
.global _start
_start:
mov r2, #24 #first set of integers
mov r4, #18
bl mysub1
bl mysub2
bl mysub3
mov r2, #78 #second set of integers
mov r4, #34
bl mysub1
bl mysub2
bl mysub3
mov r2, #99 #third set of integers
mov r4, #36
bl mysub1
bl mysub2
bl mysub3
_exit:
mov r7, #1
swi 0
mysub1: #subroutine to find gcd
cmp r2, r4
beq done
bgt greater
blt less
greater:
sub r2, r2, r4
bal mysub1
less:
sub r4, r4, r2
bal mysub1
done:
bx lr
mysub2: #subroutine to convert gcd result to ascii value
add r4, #48
ldr r9, =store
str r4, [r9]
mov r7, #4 #print out a newline
mov r0, #1
mov r2, #1
ldr r1, =newline
swi 0
bx lr
mysub3: #subroutine to print out the ascii value
mov r7, #4
mov r0, #1
mov r2, #2
ldr r1, =store
swi 0
bx lr
.data
store:
.space 2
newline:
.ascii "\n"
This is the culprint:
add r4, #48
ldr r9, =store
str r4, [r9]
This code has two bugs:
it only works for numbers between 0 and 9
str r4, [r9] stores four bytes to store, overwriting the newline right after the two-byte buffer.
To fix the first issue, you need to do a division with rest to separate the number in r4 into two digits. To fix the second issue, use strb or strh to store a byte or halfword instead as to not overrun the buffer.

Can't get newline to print with ARM Linux assembly

I started with code from a Raspberry Pi assembly language book. It prints out 15 in binary as so:
00000000000000000000000000001111pi#raspberrypi:$
I wanted to add a newline at the end, so I implemented the _newline: and new: .ascii "\n" portion of the code.
I reassembled it, but the output remains the same. Did I miss something in outputting the newline?
.global _start
_start:
mov r6, #15
mov r10, #1
mov r9, r10, lsl #31
ldr r1, =string
_bits:
tst r6, r9
moveq r0, #48
movne r0, #49
str r0, [r1]
mov r8, r6
bl _write
mov r6, r8
movs r9, r9, lsr #1
bne _bits
_newline:
mov r0, #1
mov r2, #1
mov r7, #4
ldr r1, =new
swi 0
_exit:
mov r7, #1
swi 0
_write:
mov r0, #1
mov r2, #1
mov r7, #4
swi 0
bx lr
.data
string: .ascii " "
new: .ascii "\n"
The last few lines of strace output are:
write(1, "1", 11) = 1
write(1, "1", 11) = 1
write(1, "1", 11) = 1
write(1, "1", 11) = 1
write(1, "\0", 11) = 1
exit(1) =?
+++ exited with 1 +++
Your strace output is the clue: write(1, "\0", 11) = 1 shows us that you wrote a 0 byte instead of the ASCII encoding of \n.
When you str r0, [r1], you're storing 4 bytes.
The destination of that store is
.data
string: .ascii " "
new: .ascii "\n"
which is really:
.data
string: .byte ' '
new: .byte '\n'
So each time you store '0' or '1' to string, you're also writing 3 more zero bytes, clobbering your '\n' and 2 more bytes beyond the end of your data section. (It doesn't segfault because you're not right at the end of a page.)
The simplest fix is to use a single-byte store: strb r0, [r1] instead of the word-sized str.

Refering to named constant in ARM assembly syntax / gas?

When I try to compile this ARM asm with as (arm-linux-gnueabihf):
.data
len = 42
.text
mov r0, #13
...it works. However, when I replace #13 with =len:
.data
len = 42
.text
mov r0, =len
I get:
Error: immediate expression requires a # prefix -- `mov r0,=len'
I've tried #len and #=len, neither seem to work. How do I refer to a named constants from the .data section in the .text section in ARM syntax?
Update:
Yeah, I had gotten section addresses and constants confused. For posterity, here is ARM hello world in unified syntax:
.syntax unified
.data
msg:
.ascii "Hello, ARM!\n"
len = . - msg
.text
.globl _start
_start:
mov r0, 1
ldr r1, =msg
mov r2, len
mov r7, 4
svc 0
mov r0, 0
mov r7, 1
svc 0

Resources