Marco Lugo Marco Lugo - 3 months ago 14
Linux Question

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 +++

Answer

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.