2

I'm attempting to write the integer contents of a register to a text file in ARM Assembly. I have been reading with little success - I have deduced from reading the technical manual I will require some SWI instruction, but I cannot for the life of me find a concrete example of how to do this.

Operating system is Raspbian running on Pi B model.

Thank you in advance for any help, if you require any clarifications please let me know!

EDIT : To clarify, I am assembling and executing my code successfully using GCC. I want to store the values of my data registers to a text file.

Example :

.global main
.func main

main:
    mov r1, #19
    mov r2, #11
    add r0, r1, r2
    bx lr

In the above case, r0 would hold the value 30. I want to write that value to a text file.

foaf
  • 121
  • 1
  • 2
  • 8
  • It is much easier to get help when you ask concrete questions. – auselen Mar 02 '15 at 19:23
  • @auselen - what more could I add? Assume a simple assembly program which stores the value 3 in r0. I now want to write the contents of r0 to a txt file. I am not sure what else you would like, but please tell me. – foaf Mar 02 '15 at 19:28
  • 1
    Writing a '3' to a file is not as writing any integer. Are you able to write ~`itoa` in C? Do you know how to write '3' to a text file? Why not to just STDOUT? Do you know the difference between a file and STDOUT? Are you able to use the tools to produce an executable from an assembly file? Since I don't know your foundations, I don't know where to start answering. – auselen Mar 02 '15 at 19:54
  • Anyway I added answer to other question: http://stackoverflow.com/a/28818270/1163019 – auselen Mar 02 '15 at 19:54
  • @auselen, I haven't written any C, my background is in Java & C# and this is my first dabble into ARM assembly, so thank you for taking the time to reply to me. I understand the idea behind STDOUT and yes, I am able to use the tools to produce an executable from the assembly files, and have done so successfully so far. What I would like to do, and as of yet have been unable to find any information on, is storing the contents of the data registers into a file on disk at the end of execution. Is this achievable with STDOUT in assembly? Edit: I should also add i'm using GNU Compiler. Thanks! – foaf Mar 02 '15 at 20:07
  • 2
    Assembly language itself has no concept of anything beyond instructions, registers and memory addresses. Since you'd essentially end up implementing `fopen()`, `fwrite()`, `fclose()` and possibly various other bits of the C library that's already right there, there's a strong argument for just linking the C library and calling its I/O functions directly (learning the details of calling conventions in the process). Of course, that's not to say you _shouldn't_ learn the details of the OS interface, just that it's possibly something that can wait. – Notlikethat Mar 02 '15 at 20:15
  • @Notlikethat - that seems to make alot of sense. I was unaware you could call C functions from within Assembly. is there a definitive source/tutorial for this, or could you recommend something to get me started? Thank you again. If you want to write that as an answer i'll happily mark it as such. – foaf Mar 02 '15 at 20:26
  • not necessarily fopen right? open should do ok. – auselen Mar 03 '15 at 00:24

1 Answers1

0

I did give this a try, thinking about things you need to know beforehand. Of course there are many ways to utilize assembly programming but I aimed for no help from the compiler or libraries.

  • Be able to use toolchain correctly
  • Linker expects a _start symbol
  • Define a string, address it
  • Constants for O_WRONLY, O_CREAT
  • How to encode permission
  • Find out call signatures of open, write, fsync, close, exit
  • How to make a syscall
  • Some kind of memory management, I used stack
  • Pointers
  • ASCII representation of a digit
  • Load / Store of registers, addressing modes
  • How to debug! Funny thing I started thinking this should be straight forward only to find out hard way that you need to call fsync before exiting the process to ask kernel for flushing. Probably O_DIRECT | O_SYNC is an easier choice.

    $ as open_e.s -o open_e.o
    $ ld open_e.o -o open_e
    $ cat open_e.s
    .global _start
    
    _start:
    @open syscall 
    ldr r0, =filename
    mov r1, #0101 @ O_WRONLY | O_CREAT
    ldr r2, =0666 @ permissions
    mov r7, #5 @ 5 is system call number for open
    svc #0
    cmp r0, #0
    blt exit
    
    @r0 contains fd (file descriptor, an integer)
    mov r5, r0
    
    @write syscall
    @use stack as buffer
    sub sp, #8 @ stack is full descending, this is how we leave some space
    mov r1, #'4'
    strb r1, [sp]
    mov r1, #'2'
    strb r1, [sp, #1]
    mov r1, #'\n'
    strb r1, [sp, #2]
    mov r1, sp
    mov r2, #3
    mov r7, #4 @ 4 is write
    svc #0
    
    @fsync syscall
    mov r0, r5
    mov r7, #118
    svc #0
    
    @close syscall
    mov r7, #6 @ 6 is close
    svc #0
    
    exit:
    mov r0, #0
    mov r7, #1
    svc #0
    
    .data
    .align 2
    filename: .asciz "out.txt"
    
auselen
  • 27,577
  • 7
  • 73
  • 114