User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Asm tuts

Thu Mar 21, 2013 11:48 am

Would anyone find assembly tuts useful under linux on the raspberry pi.
If so what examples would you be interested in seeing examples of ?.
Batteries not included, Some assembly required.

User avatar
malakai
Posts: 1382
Joined: Sat Sep 15, 2012 10:35 am
Contact: Website

Re: Asm tuts

Thu Mar 21, 2013 12:13 pm

I would love to see some. I still have this book on my things to get list http://www.amazon.com/Raspberry-Pi-Asse ... 148112790X I think maybe some easy games or anything could be helpful.
http://www.raspians.com - always looking for content feel free to ask to have it posted. Or sign up and message me to become a contributor to the site. Raspians is not affiliated with the Raspberry Pi Foundation. (RPi's + You = Raspians)

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Fri Mar 29, 2013 7:30 am

Hi DexOS,
I'd love some assembly tutorials.
:)

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Sat Mar 30, 2013 7:55 am

I am particulaly keen to learn the system calls to get input from the keyboard and write out to the screen, eg to take in some numbers, apply a function and print the result. I know how to do this by calling printf, but that's not pure asm.

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: Asm tuts

Sat Mar 30, 2013 9:29 am

malakai wrote:I would love to see some. I still have this book on my things to get list http://www.amazon.com/Raspberry-Pi-Asse ... 148112790X I think maybe some easy games or anything could be helpful.
that's for riscos so won't do you much good.

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 20753
Joined: Sat Jul 30, 2011 7:41 pm

Re: Asm tuts

Sat Mar 30, 2013 10:28 am

sej7278 wrote:
malakai wrote:I would love to see some. I still have this book on my things to get list http://www.amazon.com/Raspberry-Pi-Asse ... 148112790X I think maybe some easy games or anything could be helpful.
that's for riscos so won't do you much good.
Why not? The underlying assembly language is exactly the same between RISCOS and Linux (and anything else on the Raspi) so all the principles apply. And it's so easy to move to and from OS's on the Raspi..
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Please direct all questions to the forum, I do not do support via PM.

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Asm tuts

Sat Mar 30, 2013 11:46 am

I was going to write some tuts, but when i saw just one reply, i thought theres no demand.
So i will write some tuts, but for now to give you a taste, of asm coding for linux arm, heres some examples for the pi and linux.
But first note, i use a assembler called FasmArm, which does not have a Arm port (i am working on this), so for now you need to assembly theres examples on windows or x86 linux.
Once you have assembled the code, you will need to right click on the file, then click "properties", them "permissions" and click the "Allow executing as program"
Then you can run them on the pi from a terminal like this:
./filename <enter>
or some may need
sudo /filename <enter>
Replace filename with the name of file.
First the classic hello world

Code: Select all

format ELF executable
entry start
include 'ArmMacro.inc'
segment readable writeable executable

start:                          ;                   (x86    code)
                                ;
        mov       r0, 0x1       ; fd -> stdout      (mov    ebx,1)
        load_reg  r1, msg       ; buf -> msg        (mov    ecx,msg)
        load_reg  r2, msg_size  ; count -> len(msg) (mov    edx,msg_size)
        mov       r7, 0x4       ; write is syscall  (mov    eax,4
        swi       0x0           ; invoke syscall    (int    80h)
                                ;
        mov       r0, 0x0       ; status -> 0       (xor    ebx,ebx)
        mov       r7, 0x1       ; exit is syscall 1 (mov    eax,1)
        swi       0x0           ; invoke syscall    (int    80h)
                                ;
segment readable writeable      ;
                                ;
msg db "Hello from FasmArm, on the Raspberry Pi ",0xa  ; Message
msg_size = $-msg                                                      
In the above example i have included the x86 assembly code to compare.
The "ArmMacro.inc" needed for the above

Code: Select all

; -----------------------------------------------------  ;
; Use load_reg Rd,$12345678 in your code etc...          ;
; -----------------------------------------------------  ;
macro load_reg reg,immediate {                           ;
mov reg,immediate and $FF                                ;
orr reg,reg,immediate and $FF00                          ;
orr reg,reg,immediate and $FF0000                        ;
orr reg,reg,immediate and $FF000000                      ;
}                                                        ; 
Same as above but change text color

Code: Select all

; Same as print, but changes color of text
format ELF executable
entry start
include 'ArmMacro.inc'
segment readable writeable executable

start:
                                ;
        mov       r0, 0x1       ; fd -> stdout      (mov    ebx,1)
        load_reg  r1, msg       ; buf -> msg        (mov    ecx,msg)
        load_reg  r2, msg_size  ; count -> len(msg) (mov    edx,msg_size)
        mov       r7, 0x4       ; write is syscall  (mov    eax,4
        swi       0x0           ; invoke syscall    (int    80h)
                                ;
        mov       r0, 0x0       ; status -> 0       (xor    ebx,ebx)
        mov       r7, 0x1       ; exit is syscall 1 (mov    eax,1)
        swi       0x0           ; invoke syscall    (int    80h)
                                ;

segment readable writeable


msg db 1bh, "[0;31;49m Your message", 1bh, "[0;39;49m",0xa   ;1bh, "[0;31;49m = red on black
msg_size = $-msg                                             ;1bh, "[0;39;49m" =restore default color
Get user input

Code: Select all

; Get user input
format ELF executable
entry start
include 'ArmMacro.inc'
segment readable writeable executable

start:                                ;
        mov       r0, 0x1             ;
        load_reg  r1, msg             ;
        load_reg  r2, msg_size        ;
        mov       r7, 0x4             ;
        swi       0x0                 ;
                                      ;
        mov       r7, 0x3             ;
        mov       r0, 0x1             ;
        load_reg  r1, inp_buf         ;
        load_reg  r2, 0x100           ;
        swi       0x0                 ;
                                      ;
        load_reg  r1, inp_buf_size    ;
        str       r0, [r1]            ;
                                      ;
        mov       r0, 0x1             ;
        load_reg  r1, msg2            ;
        load_reg  r2, msg2_size       ;
        mov       r7, 0x4             ;
        swi       0x0                 ;
                                      ;
        mov       r0, 0x1             ;
        load_reg  r1, inp_buf         ;
        load_reg  r2, inp_buf_size    ;
        ldr       r2, [r2]            ;
        mov       r7, 0x4             ;
        swi       0x0                 ;
                                      ;
        mov       r0, 0x1             ;
        load_reg  r1, crlf            ;
        load_reg  r2, 0x1             ;
        mov       r7, 0x4             ;
        swi       0x0                 ;
                                      ;
        mov       r0, 0x0             ;
        mov       r7, 0x1             ;
        swi       0x0                 ;
                                      ;
segment readable writeable            ;
                                      ;
crlf db 0ah                           ;
                                      ;
msg db 'Input some data: '            ;
msg_size = $-msg                      ;
                                      ;
inp_buf rb 100h                       ;
inp_buf_size rw 1                     ;
                                      ;
msg2 db 'You entered: '               ;
msg2_size = $-msg2                    ;
                                      ;        
And here a very small full working http server

Code: Select all

;======================================================;
; Tiny Server.                                         ;
;------------------------------------------------------;
; By Craig Bamford (Dex)                  (11-03-2013) ;
;------------------------------------------------------;
format ELF executable                                  ;
entry start                                            ;
;======================================================;
; Is logging enabled ?                                 ;
;------------------------------------------------------;
LOGGING = 1                                            ;
LOGGING2 = 0                                           ;
;======================================================;
; Def                                                  ;
;------------------------------------------------------;
SOCK_STREAM       = 1                                  ;
AF_INET           = 2                                  ;
SYS_socketcall    = 102                                ;
SYS_SOCKET        = 1                                  ;
SYS_CONNECT       = 3                                  ;
SYS_SEND          = 9                                  ;
SYS_RECV          = 10                                 ;
IPPROTO_TCP       = 6                                  ;   Transmission Control Protocol
;======================================================;
; Print macro                                          ;
;------------------------------------------------------;
macro print _msg,_msglen                               ;
{ common                                               ;
        push      (r0)                                 ;
        push      (r1)                                 ;
        push      (r2)                                 ;
        push      (r7)                                 ;
        mov       r7, 0x4                              ;
        mov       r0, 0x1                              ;
        imm32     r1, _msg                             ;
        imm32     r2, _msglen                          ;
        swi       0x0                                  ;
                                                       ;
        pop       (r7)                                 ;
        pop       (r2)                                 ;
        pop       (r1)                                 ;
        pop       (r0)                                 ;
}                                                      ;
;======================================================;
; old tcpsend macro                                    ;
;------------------------------------------------------;
macro tcpsend _msg,_msglen                             ;
{ common                                               ;
        push      (r0)                                 ;
        push      (r1)                                 ;
        push      (r2)                                 ;
        push      (r3)                                 ;
        push      (r7)                                 ;
        imm32     r0, clientfd                         ;
        ldr       r0, [r0]                             ;
        imm32     r1, _msg                             ;
        imm32     r2, _msglen                          ;
        mov       r3, 0                                ;
        imm32     r7, 0x121                            ;
        swi       0x0                                  ;
        pop       (r7)                                 ;
        pop       (r3)                                 ;
        pop       (r2)                                 ;
        pop       (r1)                                 ;
        pop       (r0)                                 ;
}                                                      ;
;======================================================;
; old tcpsend macro                                    ;
;------------------------------------------------------;
; r0 = size to send                                    ;
;------------------------------------------------------;
macro tcpsend_reg _msg                                 ;
{ common                                               ;
        push      (r0)                                 ;
        push      (r1)                                 ;
        push      (r2)                                 ;
        push      (r3)                                 ;
        push      (r7)                                 ;
        mov       r2, r0                               ;
        imm32     r0, clientfd                         ;
        ldr       r0, [r0]                             ;
        imm32     r1, _msg                             ;
        mov       r3, 0                                ;
        imm32     r7, 0x121                            ;
        swi       0x0                                  ;
        pop       (r7)                                 ;
        pop       (r3)                                 ;
        pop       (r2)                                 ;
        pop       (r1)                                 ;
        pop       (r0)                                 ;
}                                                      ;
;======================================================;
; Print macro                                          ;
;------------------------------------------------------;
;  r0 = string size                                    ;
;------------------------------------------------------;
macro print_reg _msg,_msglen                           ;
{ common                                               ;
        push      (r0)                                 ;
        push      (r1)                                 ;
        push      (r2)                                 ;
        push      (r7)                                 ;
        mov       r2, r0                               ;
        mov       r7, 0x4                              ;
        mov       r0, 0x1                              ;
        imm32     r1, _msg                             ;
        swi       0x0                                  ;
                                                       ;
        pop       (r7)                                 ;
        pop       (r2)                                 ;
        pop       (r1)                                 ;
        pop       (r0)                                 ;
}                                                      ;
include 'FasmArm.inc'                              ;
segment readable writeable executable                  ;
;======================================================;
; Main start                                           ;
;------------------------------------------------------;
start:                                                 ;
        print msg,msg.msg_size                         ; print start message
;======================================================;
; Check commamd line for port number                   ;
;------------------------------------------------------;
        ldmfd     sp!, {r1}                            ;
        imm32     r0, argc                             ;
        str       r1, [r0]                             ;
        mov       r0, 80                               ; default port number
        cmp       r1, 1                                ;
;======================================================;
; If no number, use default (port 80)                  ;
;------------------------------------------------------;
        beq       UseDeFault                           ;
;======================================================;
; Convet  port number                                  ;
;------------------------------------------------------;
        ldmfd     sp!,{r1}                             ;
        ldmfd     sp!,{r3}                             ;
        mov       r4, 10                               ;
        bl        StrToInt                             ;
        mov       r0, r1                               ;
        imm32     r1, portnumber                       ;
        str       r0, [r1]                             ;
align 4                                                ;
UseDeFault:                                            ;
;======================================================;
; Store Port                                           ;
;------------------------------------------------------;
        rev16     r0, r0                               ; byte order
        imm32     r1, sockaddr_in.sin_port             ;
        strh      r0, [r1]                             ;
;======================================================;
; SOCKET(2)                                            ;
;------------------------------------------------------;
; Creates an endpoint for communication and returns    ;
; a descriptor.                                        ;
;------------------------------------------------------;                                                          ;
        imm32     r7, 0x119                            ; socket sys number
        mov       r0, AF_INET                          ;
        mov       r1, SOCK_STREAM                      ;
        mov       r2, 0                                ;
        swi       0x0                                  ;
        teq       r0, 0                                ;
        bpl       bind                                 ; branch if not neg
                                                       ;
        mvn       r0, r0                               ;
        add       r0, 1                                ; change neg to pos number
        imm32     r1, 4096                             ; We need to check because some times address is neg
        cmp       r0, r1                               ;
        bl        Convert2Hex                          ; Get error code
        print     print_hex_string,print_hex_string_size ;
        print     msgE1,msgE1.msgE1_size               ; error message 1
        b         fin                                  ; branch exit
align 4                                                ;
;======================================================;
; BIND(2)                                              ;
;------------------------------------------------------;
; When a socket is created with socket(2),             ;
; it exists in a name space (address family) but has   ;
; no address assigned to it. bind() assigns the        ;
; address specified to by addr to the socket referred  ;
; to by the file descriptor sockfd. addrlen specifies  ;
; the size, in bytes, of the address structure pointed ;
; to by addr. Traditionally, this operation is called  ;
; "assigning a name to a socket".                      ;
;------------------------------------------------------;
bind:                                                  ; Ok  SOCKET(2)
        imm32     r1, sockfd                           ;
        str       r0, [r1]                             ;
                                                       ;
        imm32     r0, sockfd                           ; bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        ldr       r0, [r0]                             ;
        imm32     r1, sockaddr_in                      ;
        imm32     r2, dest_size                        ;
        imm32     r7, 0x11A                            ; BIND(2)
        swi       0x0                                  ;
                                                       ;
        teq       r0, 0                                ; check for errors
        bpl       listen                               ; branch if not neg
                                                       ;
        mvn       r0, r0                               ;
        add       r0, 1                                ; change neg to pos number
        imm32     r1, 4096                             ; We need to check because some times address is neg
        cmp       r0, r1                               ;
        bl        Convert2Hex                          ; Get error code
        print     print_hex_string,print_hex_string_size ;
        print     msgE2,msgE2.msgE2_size               ; error message 1
        b         fin                                  ; branch exit
                                                       ; Ok BIND(2)
;======================================================;
; LISTEN(2)                                            ;
;------------------------------------------------------;
; Start to listen for incomming connections,           ;
; allowing for a queue size of                         ;
; waiting connections of 20.                           ;
;------------------------------------------------------;
align 4                                                ;
listen:                                                ;
        imm32     r0, sockfd                           ; listen(int sockfd, int backlog);
        ldr       r0, [r0]                             ;
        mov       r1, 0                                ; was 20 *****
        imm32     r7, 0x11C                            ; LISTEN(2)
        swi       0x0                                  ;
                                                       ;
        teq       r0, 0                                ; check for errors
        bpl       infinity                             ; branch if not neg
                                                       ;
        mvn       r0, r0                               ;
        add       r0, 1                                ; change neg to pos number
        imm32     r1, 4096                             ; We need to check because some times address is neg
        cmp       r0, r1                               ;
        bl        Convert2Hex                          ; Get error code
        print     print_hex_string,print_hex_string_size ;
        print     msgE3,msgE3.msgE3_size               ;  error message 1
        b         fin                                  ; branch exit
align 4                                                ;
infinity:                                              ; Ok LISTEN(2)
;======================================================;
; ACCEPT(2)                                            ;
;------------------------------------------------------;
; The accept() system call is used with                ;
; connection-based socket types (SOCK_STREAM,          ;
; SOCK_SEQPACKET). It extracts the first connection    ;
; request on the queue of pending connections for the  ;
; listening socket, sockfd, creates a new connected    ;
; socket, and returns a new file descriptor referring  ;
; to that socket. The newly created socket is not in   ;
; the listening state. The original socket sockfd is   ;
; unaffected by this call.                             ;
;------------------------------------------------------;
accept_loop:                                           ;
        imm32     r0, sockfd                           ;
        ldr       r0, [r0]                             ;
        imm32     r1, client_addr_ip                   ; client_addr
        imm32     r2, sixteen                          ; addrlen
        imm32     r7, 0x11D                            ; ACCEPT(2)
        swi       0x0                                  ;
                                                       ;
        teq       r0, 0                                ; check for errors
        bgt       accept_ok                            ;
if LOGGING2                                            ;
        mvn       r0, r0                               ;
        add       r0, 1                                ; change neg to pos number
        bl        Convert2Hex                          ; Get error code
        print     print_hex_string,print_hex_string_size ;
        print     msgE4,msgE4.msgE4_size               ;  error message 1
end if                                                 ;
        b         accept_loop                          ; branch if neg or zero
align 4                                                ;
;======================================================;
; RECV(2)                                              ;
;------------------------------------------------------;
; The recv(2) and recvmsg() calls are used to receive  ;
; messages from a socket, and may be used to receive   ;
; data on a socket whether or not it is                ;
; connection-oriented.                                 ;
;                                                      ;
; If src_addr is not NULL, and the underlying protocol ;
; provides the source address, this source address is  ;
; filled in. When src_addr is NULL, nothing is filled  ;
; in, in this case, addrlen is not used, and should    ;
; also be NULL. The argument addrlen is a value-result ;
; argument, which the caller should initialize before  ;
; the call to the size of the buffer associated with   ;
; src_addr, and modified on return to indicate the     ;
; actual size of the source address. The returned      ;
; address is truncated if the buffer provided is too   ;
; small,                                               ;
; in this case, addrlen will return a value            ;
; greater than was supplied to the call.               ;
;------------------------------------------------------;
accept_ok:                                             ;
        imm32     r1, clientfd                         ;
        str       r0, [r1]                             ;
recv_loop:                                             ;
        imm32     r0, clientfd                         ;
        ldr       r0, [r0]                             ; client FD
        imm32     r1, buffer                           ; buffer
        imm32     r2, bufferlen                        ; buffer size
        imm32     r3, 0                                ; No options
        imm32     r7, 0x123                            ; RECV(2)
        swi       0x0                                  ;
                                                       ;
        teq       r0, 0                                ; check for errors
        blt       recv_loop                            ;
        imm32     r1, recv_size                        ; get size of message
        str       r0, [r1]                             ; store it
;======================================================;
; if logging2 then print buffer                        ;
;------------------------------------------------------;
if LOGGING2                                            ;
        print     buffer, bufferlen                    ;
;======================================================;
; Next line                                            ;
;------------------------------------------------------;
        print     NextLine, NextLine.NextLine_size     ;
                                                       ;
end if                                                 ;
;======================================================;
; test for file                                        ;
;------------------------------------------------------;
        imm32     r0, buffer                           ;
        ldr       r2, [r0], 4                          ;
        imm32     r3, 'GET '                           ;
        cmp       r2, r3                               ;
        bne       close                                ;
        eor       r1, r1                               ;
        ldrb      r2, [r0], 1                          ;
        cmp       r2, '/'                              ;
        bne       close                                ;
filewantedloop:                                        ;
        ldrb      r2, [r0], 1                          ;
        cmp       r2, ' '                              ;
        beq       ItsSpace                             ;
                                                       ;
        imm32     r3, bufferwantedfile                 ;
        strb      r2, [r3,r1]                          ;
        add       r1, 1                                ;
        b         filewantedloop                       ;
ItsSpace:                                              ;
        imm32     r3, bufferwantedfile                 ;
        cmp       r1,0                                 ;
        bne       Notjustspace                         ;
        imm32     r6,"inde"                            ;
        str       r6,[r3],4                            ;
        imm32     r6,"x.ht"                            ;
        str       r6,[r3],4                            ;
        imm32     r6,"m"                               ;
        strb      r6,[r3]                              ;
        imm32     r3, bufferwantedfile                 ;
        mov       r1,9                                 ;
Notjustspace:                                          ;
        mov       r4, 0                                ;
        strb      r4, [r3,r1]                          ;
        imm32     r4, offset                           ;
        str       r1, [r4]                             ;
;======================================================;
; Is logging enabled ?                                 ;
;------------------------------------------------------;
; If logging has been enabled, itll use the function   ;
; called ntop (at the bottom of this code) to convert  ;
; the IP address of the person who connected to the    ;
; server into a string form and print it.              ;
;------------------------------------------------------;
if LOGGING                                             ;
        imm32     r2, client_addr_ip                   ;
        ldr       r0, [r2, 4]                          ; mov eax, dword [peeraddr+4]
        imm32     r3, client_addr_ip_Converted         ; mov edi, buffer+bufferlen-16
        bl        ntop                                 ; call ntop
        print_reg   client_addr_ip_Converted           ;
end if                                                 ;
;======================================================;
; get file info                                        ;
;------------------------------------------------------;
fileisnamed:                                           ;
        mov       r7, 106                              ;
        imm32     r0, bufferwantedfile                 ;
        imm32     r1, stat                             ;
        swi       0x0                                  ;
        cmp       r0, 0                                ;
        beq       openfile                             ;
                                                       ;
;======================================================;
; file not found                                       ;
;------------------------------------------------------;
        tcpsend   h404,h404.len                        ;
;======================================================;
; if logging print 404 message                         ;
;------------------------------------------------------;
if LOGGING                                             ;
        print     l404,l404.len                        ;
;======================================================;
; Print wanted file name                               ;
;------------------------------------------------------;
        imm32     r2, offset                           ;
        ldr       r2, [r2]                             ;
        mov       r7, 0x4                              ;
        mov       r0, 0x1                              ;
        imm32     r1, bufferwantedfile                 ;
                                                       ;
        swi       0x0                                  ;
;======================================================;
; Next line                                            ;
;------------------------------------------------------;
        print     NextLine, NextLine.NextLine_size     ;
end if                                                 ;
        b         close                                ;
                                                       ;
;======================================================;
; Try to open file                                     ;
;------------------------------------------------------;
openfile:                                              ;
        imm32     r4, stat                             ;
        ldr       r0, [r4,20]                          ;
        imm32     r5, fdlen                            ;
        str       r0, [r5]                             ;
        mov       r7, 5                                ;
        imm32     r0, bufferwantedfile                 ;
        mov       r1 ,0                                ;
        mov       r2 ,0                                ;
        swi       0x0                                  ;
        teq       r0, 0                                ; check for errors
        bgt       fd_ok                                ;
;======================================================;
; Error when opeing file                               ;
;------------------------------------------------------;
        mvn       r0, r0                               ;
        add       r0, 1                                ; change neg to pos number
        bl        Convert2Hex                          ;
        print     print_hex_string, print_hex_string_size
        print     fderror,fderror_len                  ;
        b         close                                ;
;======================================================;
; file found and ready to send                         ;
;------------------------------------------------------;
fd_ok:                                                 ;
        imm32     r1, fd                               ;
        str       r0, [r1]                             ;
;======================================================;
; if logging, print 200 OK message                     ;
;------------------------------------------------------;
if LOGGING                                             ;
        print     l200,l200.len                        ;
;======================================================;
; Print wanted file name                               ;
;------------------------------------------------------;
        imm32     r2, offset                           ;
        ldr       r2, [r2]                             ;
        mov       r7, 0x4                              ;
        mov       r0, 0x1                              ;
        imm32     r1, bufferwantedfile                 ;
                                                       ;
        swi       0x0                                  ;
;======================================================;
; Next line                                            ;
;------------------------------------------------------;
        print     NextLine, NextLine.NextLine_size     ;
end if                                                 ;
;======================================================;
; set header (eg: file size)                           ;
;------------------------------------------------------;
        imm32     r0, fdlen                            ;
        ldr       r0, [r0]                             ;
        imm32     r10, c_l                             ;
        bl        IntToStr                             ;
        mov       r1, 13                               ;
        strb      r1, [r10],1                          ;
        mov       r1, 10                               ;
        strb      r1, [r10],1                          ;
        mov       r1, 13                               ;
        strb      r1, [r10],1                          ;
        mov       r1, 10                               ;
        strb      r1, [r10],1                          ;
                                                       ;
        imm32     r1, c_l                              ;
        sub       r10, r1                              ;
        imm32     r0, h200.len                         ;
        add       r0, r10                              ;
       ; print     NextLine, NextLine.NextLine_size    ;
       ; print_reg h200 ;, h200.len                    ; temp
       ; print     NextLine, NextLine.NextLine_size    ;
;======================================================;
; send header                                          ;
;------------------------------------------------------;
        tcpsend_reg h200                               ;
;======================================================;
; Send file                                            ;
;------------------------------------------------------;
        mov       r7, 187                              ;
        imm32     r0, clientfd                         ;
        ldr       r0, [r0]                             ;
        imm32     r1, fd                               ;
        ldr       r1, [r1]                             ;
        mov       r2, 0                                ;
        imm32     r3, fdlen                            ;
        ldr       r3, [r3]                             ;
        mov       r4, 0                                ;
        swi       0x0                                  ;
                                                       ;
align 4                                                ;
;======================================================;
; Close socket and wait                                ;
;------------------------------------------------------;
close:                                                 ;
        mov       r7, 6                                ;
        imm32     r0, fd                               ;
        ldr       r0, [r0]                             ;
        swi       0x0                                  ;
        mov       r7, 6                                ; CLOSE(2)
        imm32     r0, clientfd                         ;
        ldr       r0, [r0]                             ;
        swi       0x0                                  ;
        imm32     r0,buffer                            ;
        eor       r1,r1                                ;
        imm32     r2,bufferlen                         ;
        mov       r2,r2, lsr 2                         ;
align 4                                                ;
ClearBuffLoop:                                         ;
        str       r1,[r0],4                            ;
        subs      r2,r2,1                              ;
        bne       ClearBuffLoop                        ;
        b         infinity                             ;
align 4                                                ;
;======================================================;
; Close server and exit                                ;
;------------------------------------------------------;
fin:                                                   ; exit
        print     msgclose,msgclose.msgclose_size      ;
        mov       r0, 0x0                              ;
        mov       r7, 0x1                              ;
        swi       0x0                                  ;
                                                       ;
;======================================================;
; Converts to hex                                      ;
;  r0  = number ( prints 8 hex digits)                 ;
;------------------------------------------------------;
align 4                                                ;
Convert2Hex:                                           ;
        stmfd     sp!, {r0-r12, lr}                    ;
        imm32     r2,hex_digits                        ;
        imm32     r3,print_hex_string                  ;
        mov       r4,28                                ;
align 4                                                ;
print_hex_loop:                                        ;
        mov       r1,r0,lsr r4                         ; Get digit n
        and       r1,r1,0x0f                           ; mask off lower nibble
        ldrb      r1,[r2,r1]                           ; r0 now contains a hex number,
                                                       ; look it up in table
        strb      r1,[r3],1                            ;
        subs      r4,r4,4                              ;
        bpl       print_hex_loop                       ;
                                                       ;
        ldmfd     sp!, {r0-r12, pc}                    ; pop & return
align 4                                                ;
;======================================================;
; String to int                                        ;
; input: r3 = buffer, r4 = base (eg 10)                ;
; output: r1 = number                                  ;
;------------------------------------------------------;
StrToInt:                                              ;
        stmfd     sp!, {r2-r3, lr}                     ; save regs
        eor       r1, r1                               ; zero r1 and r2
        eor       r2, r2                               ;
.loop:                                                 ;
        ldrb      r2, [r3], 1                          ; load a byte
        cmp       r2, 0                                ; check for 0
        beq       .end                                 ; if so exit
        mul       r1, r1, r4                           ; multiply with basic
        sub       r2, r2, '0'                          ; sub ASCII value
        cmp       r2, 9                                ; cmpare it to 9
        ble       .ok                                  ; if its let or = jump to OK
        sub       r2, 7                                ; if not sub 7 (eg: it A-F)
.ok:                                                   ;
        add       r1, r1, r2                           ; save it
        b         .loop                                ; do another loop .loop
.end:                                                  ;
        ldmfd     sp!, {r2-r3, pc}                     ; restore regs and return.
align 4                                                ;
;======================================================;
; write number to buffer                               ;
;------------------------------------------------------;
; r10 = buffer address                                 ;
;------------------------------------------------------;
number2buffer:                                         ;
        stmfd     sp!, {lr}                            ;
        strb      r0, [r10],1                          ;
        ldmfd     sp!, {pc}                            ;
align 4                                                ;
;======================================================;
; Int To String                                        ;
;------------------------------------------------------;
; input:  r0 = number                                  ;
;         r10 = buffer                                 ;
;                                                      ;
; output: r10 = buffer + offset                        ;
;------------------------------------------------------;                                                ;
IntToStr:                                              ;
        stmfd     sp!, {r0-r9, lr}                     ; save regs
        imm32     r8,prt_digits                        ;
                                                       ;
        imm32     r6,0                                 ; current character to print
        mov       r5,9                                 ; digits - 1 (max pos value 2147483647) (31 bits)
        imm32     r9,0                                 ;
                                                       ;
                                                       ;
        cmp       r0,0                                 ;
        beq       zeronum                              ;
        and       r7,r0,$80000000                      ; test bit 31 of r0
        cmp       r7,0                                 ;
        beq       posnum                               ; go to posnum if result equals zero (positive)
                                                       ;
        imm32     r2,$FFFFFFFF                         ;
        eor       r0,r0,r2                             ; invert all bits of r0 (convert to positive)
        mov       r2,r0                                ; backup r0 value
        add       r2,r2,1                              ; add 1 to (now positive) value
        imm32     r0,"-"                               ;
        bl        number2buffer                        ; print negative (-) sign
        mov       r0,r2                                ; restore r0 value
                                                       ;
posnum:                                                ;
        imm32     r4,1000000000                        ;
        subs      r1,r0,r4                             ; subtract r4 (power of 10 result) from starting value, store in r1
        b         Printloop                            ;
                                                       ;
align 4                                                ;
mainloop:                                              ;
        imm32     r6,0                                 ; clear r6
        mov       r2,r5                                ; back up value of r5
        b         pow10                                ; lookup power of 10 from r5
p10ret:                                                ;
        mov       r5,r2                                ; restore r5 value
        subs      r1,r1,r4                             ; subtract r4 (power of 10 result) from starting value, store in r1
                                                       ;
Printloop:                                             ;
        ;print "At Printloop"                          ;
        ;sync                                          ;
        bpl       notmatched                           ; go to notmatched if result (r1) is not negative
        add       r1,r1,r4                             ; add power of 10 value to r1
        cmp       r6,0                                 ;
        blt       nodigit                              ; if r6 is negative, reset to 0
        b numfix                                       ;
notmatched:                                            ;
        ;-print "at notmatched"                        ;
        add       r6,r6,1                              ; increment current character by 1
        subs      r1,r1,r4                             ; subtract pow10 value from r1
        b         Printloop                            ;
numfix:                                                ;
        mov       r3,r6                                ; update r3 from r6
        ldrb      r3,[r8,r3]                           ; r3 now contains a number (ascii)
        mov       r0,r3                                ; move ascii character to r0
        cmp       r9,0                                 ; if r9 does not equal zero,
        bne       allowprt                             ; go to allowprt (allow printing)
        cmp       r0,'0'                               ; if r0 equals ascii zero,
        beq       noprint                              ; go to noprint (disable printing leading zeros)
        imm32     r9,1                                 ; set r9 to 1 (allow printing zeros)
                                                       ;
allowprt:                                              ;
        bl        number2buffer                        ; print character to buffer
noprint:                                               ;
        subs      r5,r5,1                              ; decrement r5 (power of 10 mult) by 1
        mov       r0,r1                                ; replace r0 with r1
        bpl       mainloop                             ; go to mainloop if r5 is not negative
        ;sync                                          ;
        ;-end                                          ;
finish:                                                ;
        ;print "Done printing"                         ;
        ;sync                                          ;
        ldmfd     sp!, {r0-r9, pc}                     ; restore regs and return.
zeronum:                                               ;
        imm32     r0,"0"                               ;
        bl        number2buffer                        ; print negative (-) sign
        b         finish                               ;
                                                       ;
                                                       ;
nodigit:                                               ;
        imm32     r6,0                                 ;
        b         numfix                               ;
                                                       ;
pow10:  ; calculate 10^x (r5 value)                    ;
        ;r4 will contain result, r5 specifies power of 10 to calc
        imm32     r4,10                                ;
        cmp       r5,1                                 ;
        bgt       p10mul                               ;
        blt       p10p1                                ;
        imm32     r4,10                                ;
        b         p10ret                               ;
p10p1:                                                 ;
        imm32     r4,1                                 ;
        b         p10ret                               ;
p10mul:                                                ;
        sub       r5,r5,1                              ;
p10loop:                                               ;
        imm32     r7,10                                ;
        mul       r4,r4,r7                             ;
        sub       r5,r5,1                              ;
        cmp       r5,0                                 ;
        bgt       p10loop                              ;
        b         p10ret                               ;
align 4                                                ;
;======================================================;
; ntop                                                 ;
; r0 = network-order address, r3 = buffer              ;
; returns: r10 = buffer + offset                       ;
;------------------------------------------------------;
ntop:                                                  ;
; eax = network-order address, edi = buffer            ;
; returns: ecx = length                                ;
        stmfd     sp!, {r1-r12, lr}                    ; save regs push ebx edx ebp
        mov       r10,r3                               ;
        mov       r6, r3                               ;
        mov       r1, r0                               ;
        imm32     r2, 0x000000FF                       ;
        and       r0, r2                               ;
        mov       r4, 2                                ;
;num4                                                  ;
        bl        IntToStr                             ;
        imm32     r2, '.'                              ;
        strb      r2, [r10],1                          ;
;num3                                                  ;
        mov       r0, r1                               ;
        imm32     r2, 0x0000FF00                       ;
        and       r0, r2                               ;
        mov       r0, r0, lsr 8                        ;
        mov       r4, 2                                ;
        bl        IntToStr                             ;
        imm32     r2, '.'                              ;
        strb      r2, [r10],1                          ;
;num2                                                  ;
        mov       r0, r1                               ;
        imm32     r2, 0x00FF0000                       ;
        and       r0, r2                               ;
        mov       r0, r0, lsr 16                       ;
        mov       r4, 2                                ;
        bl        IntToStr                             ;
        imm32     r2, '.'                              ;
        strb      r2, [r10],1                          ;
; num1                                                 ;
        mov       r0, r1                               ;
        mov       r0, r0, lsr 24                       ;
        mov       r4, 2                                ;
        bl        IntToStr                             ;
                                                       ;
        sub       r10, r6                              ;
        mov       r0, r10                              ;
        ldmfd     sp!, {r1-r12, pc}                    ; restore regs and return.ret

; ---------------------------------------------------- ;
; OutChar              ( print 1 character to stdout ) ;
; ---------------------------------------------------- ;
; put char = r0                                        ;
; ---------------------------------------------------- ;
OutChar:                                               ;
        stmfd       sp!, {r0-r2, r7, lr}               ; Store registers
        mov         r1, sp                             ; r1  address
        mov         r0, 1                              ; r0  stdout
        mov         r2, r0                             ; r2  length
        mov         r7, 4                      ;
        swi         0                                  ;
        ldmfd       sp!, {r0-r2, r7, pc}               ; Restore registers and return
;======================================================;
; data                                                 ;
;------------------------------------------------------;
segment readable writeable                             ;
if LOGGING                                             ;
align 4                                                ;
l404 db ' - 404 NF - '                                 ;
.len = $ - l404                                        ;
align 4                                                ;
l200 db ' - 200 OK - '                                 ;
.len = $ - l200                                        ;
end if                                                 ;
align 4                                                ;
ipnumber dw     0xfefefefe                             ;
align 4                                                ;
prt_digits:                                            ;
              db "0123456789"                          ;
align 4                                                ;
hex_digits:                                            ;
                    db "0123456789ABCDEF"              ;
align 4                                                ;
print_hex_string:                                      ;
                    db "12345678", 0xa                 ; storage for 8 digit hex string,
print_hex_string_size = $-print_hex_string             ;
align 4                                                ;
client_addr_ip: rb 16                                  ;
sixteen dw 16                                          ;
align 4                                                ;
sockaddr_in:                                           ;
  .sin_family dh AF_INET                               ;
  .sin_port   dh 0                                     ;
  .sin_addr   dw 0                                     ;
  .sin_zero   rb 8                                     ;
dest_size = $-sockaddr_in                              ;
align 4                                                ;
client_addr   dw sockaddr_in                           ;
addrlen       dw dest_size                             ;
align 4                                                ;
argc          dw 0                                     ;
portnumber    dw 0                                     ;
align 4                                                ;
recv_size     dw 0                                     ;
sockfd        dw 0                                     ;
fd            dw 0                                     ;
fdlen         dw 0                                     ;
clientfd      dw 0                                     ;
offset        dw 0                                     ;
align 4                                                ;
cArray        dw 0                                     ;
              dw 0                                     ;
              dw 0                                     ;
              dw 0                                     ;
              dw 0                                     ;
align 4                                                ;
;send 'array'.                                         ;
sArray        dw 0                                     ;
              dw 0                                     ;
              dw 0                                     ;
              dw 0                                     ;
align 4                                                ;
indexfile     db ".index.htm",0                        ;
align 4                                                ;
NextLine      db " " ,0xa                              ; Next line
.NextLine_size = $-NextLine                            ;
align 4                                                ;
msgreceved    db " Server receved data" ,0xa           ; Message
.msgreceved_size = $-msgreceved                        ;
align 4                                                ;
msg    db " Server started..." ,0xa                    ; Message
.msg_size = $-msg                                      ;
align 4                                                ;
msgclose db " Server closed", 0xa                      ; Close
.msgclose_size = $-msgclose                            ;
align 4                                                ;
msgsent db " Sent file", 0xa                           ; Send
.msgsent_size = $-msgsent                              ;
                                                       ;
msgE1  db " socket() failed" ,0xa                      ; Err1
.msgE1_size = $-msgE1                                  ;
align 4                                                ;
msgE2  db " bind() failed", 0xa                        ; Err2
.msgE2_size = $-msgE2                                  ;
align 4                                                ;
msgE3  db " listen() failed", 0xa                      ; Err3
.msgE3_size = $-msgE3                                  ;
align 4                                                ;
msgE4  db " accept() failed", 0xa                      ; Err4
.msgE4_size = $-msgE4                                  ;
align 4                                                ;
msgE5  db " send() failed", 0xa                        ; Err5
.msgE5_size = $-msgE5                                  ;
align 4                                                ;
fderror db " ERROR 1", 0xa                             ;
fderror_len = $- fderror                               ;
align 4                                                ;
fderror2 db " ERROR 2", 0xa                            ;
fderror_len2 = $- fderror2                             ;
align 4                                                ;
h404 db 'HTTP/1.0 404 Not Found',13,10,13,10,'<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD><BODY><H1>File Not Found</H1></BODY></HTML>',10,13
.len = $ - h404                                        ;
align 4                                                ;
h200 db  'HTTP/1.0 200 OK',13,10                       ;
     db  'Server: DexServer',13,10                     ;
     db  'Content-Length: '                            ;
.len = $ - h200                                        ;
align 4                                                ;
c_l  db  '                                            ';
align 4                                                ;
stat  rb 88                                            ;
align 4                                                ;
buffer  rb 512                                         ;
bufferlen = $ - buffer                                 ;
align 4                                                ;
bufferwantedfile  rb 512                               ;
align 4                                                ;
client_addr_ip_Converted  rb 16                        ;
align 4                                                ;                                             
I will post using frame buffer and maping the gpio and some games etc.
Last edited by DexOS on Sat Mar 30, 2013 11:55 am, edited 1 time in total.
Batteries not included, Some assembly required.

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Asm tuts

Sat Mar 30, 2013 11:49 am

You will need this for the above server
FasmArm.inc

Code: Select all

macro imm16 reg,immediate {
  mov reg,(immediate) and $FF
  orr reg,(immediate) and $FF00
}

macro imm16eq reg,immediate {
  moveq reg,(immediate) and $FF
  orreq reg,(immediate) and $FF00
}

macro imm16ne reg,immediate {
  movne reg,(immediate) and $FF
  orrne reg,(immediate) and $FF00
}

macro imm16lt reg,immediate {
  movlt reg,(immediate) and $FF
  orrlt reg,(immediate) and $FF00
}

macro imm16gt reg,immediate {
  movgt reg,(immediate) and $FF
  orrgt reg,(immediate) and $FF00
}

macro imm32 reg,immediate {
  mov reg,(immediate) and $FF
  orr reg,(immediate) and $FF00
  orr reg,(immediate) and $FF0000
  orr reg,(immediate) and $FF000000
}

macro imm32eq reg,immediate {
  moveq reg,(immediate) and $FF
  orreq reg,(immediate) and $FF00
  orreq reg,(immediate) and $FF0000
  orreq reg,(immediate) and $FF000000
}

macro imm32ne reg,immediate {
  movne reg,(immediate) and $FF
  orrne reg,(immediate) and $FF00
  orrne reg,(immediate) and $FF0000
  orrne reg,(immediate) and $FF000000
}

macro imm32lt reg,immediate {
  movlt reg,(immediate) and $FF
  orrlt reg,(immediate) and $FF00
  orrlt reg,(immediate) and $FF0000
  orrlt reg,(immediate) and $FF000000
}

macro imm32gt reg,immediate {
  movgt reg,(immediate) and $FF
  orrgt reg,(immediate) and $FF00
  orrgt reg,(immediate) and $FF0000
  orrgt reg,(immediate) and $FF000000
}                                                          
As "jamesh" pointed out, that book will be a big help in understanding whats going on.
Batteries not included, Some assembly required.

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: Asm tuts

Sat Mar 30, 2013 12:22 pm

jamesh wrote:
sej7278 wrote:
malakai wrote:I would love to see some. I still have this book on my things to get list http://www.amazon.com/Raspberry-Pi-Asse ... 148112790X I think maybe some easy games or anything could be helpful.
that's for riscos so won't do you much good.
Why not? The underlying assembly language is exactly the same between RISCOS and Linux (and anything else on the Raspi) so all the principles apply. And it's so easy to move to and from OS's on the Raspi..
its the os-specific bits that will be the problem though - you'd have to convert SWI calls to their linux equivalents, which for graphics/sound would be a nightmare; filehandling wouldn't be great either given the very different filesystems between adfs and ext4. floating point would be interesting as essentially its not there on riscos. riscos is 26-bit armv3 or earlier not 64-bit armv6 so you're limiting register usage and missing a lot of useful instructions and addresses would be different. with riscos you generally run assembler from the basic interpreter rather than building it with gcc/binutils so where would you learn that?

i'd love to see a single program (even hello world!) that could run on linux and riscos without modification.

a linux assembler book would be better for learning linux assembler, even an android assembler book would be better than riscos.

don't get me wrong, i learnt arm assembler on riscos, but today its just a pointless place to start.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Sat Mar 30, 2013 4:26 pm

@dexOS
Many thanks for your code examples.


I've started a little blog to record how my learning of asm is going.
asm blog

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Asm tuts

Sat Mar 30, 2013 4:42 pm

antiloquax wrote:@dexOS
Many thanks for your code examples.


I've started a little blog to record how my learning of asm is going.
asm blog
Your welcome and blogs like your's are a good way to keep a record of your progress and helps others.
Batteries not included, Some assembly required.

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 20753
Joined: Sat Jul 30, 2011 7:41 pm

Re: Asm tuts

Sat Mar 30, 2013 6:22 pm

sej7278 wrote: a linux assembler book would be better for learning linux assembler, even an android assembler book would be better than riscos.

don't get me wrong, i learnt arm assembler on riscos, but today its just a pointless place to start.
Rubbish.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Please direct all questions to the forum, I do not do support via PM.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Sat Mar 30, 2013 6:42 pm

Regarding the RISCos book. I am keen to do "pure" asm in Linux using the GNU assembler, but I am finding that book helpful.
For instance, I just used it to help me refactor some code from the book "Programming from the Ground Up" into ARM assembly code.
It's the program to find the maximum from a series of numbers.
Bruce Smith's book made it a lot easier for me to figure out how to step through a series of numbers.
:mrgreen:

And thank you to dexOS for your words of encouragement. Is it okay with you if I post up versions of your examples (once I've got to grips with them and got them working with GAS)?
mark

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: Asm tuts

Sat Mar 30, 2013 7:46 pm

jamesh wrote:
sej7278 wrote: a linux assembler book would be better for learning linux assembler, even an android assembler book would be better than riscos.

don't get me wrong, i learnt arm assembler on riscos, but today its just a pointless place to start.
Rubbish.
we seem to disagree on pretty much everything, so i'm walking away from this one.

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Asm tuts

Sat Mar 30, 2013 7:50 pm

antiloquax wrote:And thank you to dexOS for your words of encouragement. Is it okay with you if I post up versions of your examples (once I've got to grips with them and got them working with GAS)?
mark
Sure that will be fine :) .

I have just done my first RiscOS hello world using FasmArm, which was not simple as it does not output the right file format, but luckly i found a example of the smallest header needed on the net and converted it to fasmarm.
In case it helps others:

Code: Select all

format binary as ''

OS_Write0 = 0x02    ; Define the two system calls
OS_Exit   = 0x11    ; used in this code
                    ;
org 0x8000          ; org (may not be needed ?
use32               ; use 32bit
mov r0,r0           ; Decompression code call
mov r0,r0           ; Self-relocation code call
mov r0,r0           ; Zero initialisation code call
bl  start           ; Program entry call
swi OS_Exit         ; Fall-out trap to force exit
dw  0x40            ; Read-only area size (header)
dw  0x20            ; Read-write area size (code)
dw  0               ; Debug area size
dw  0               ; Zero initialisation size
dw  0               ; Debug type
dw  0x8000          ; Current base of absolute
dw  0               ; Workspace required
dw  32              ; Flag software as 32 bit PCR okay
dw  0               ; Data base address when linked
dw  0               ; Reserved header (should be zero)
dw  0               ; Reserved header (should be zero
message:
db "Hello World! :-)",0xa ,0
align 4
start:
adr r0,message      ; Pointer to message
swi OS_Write0       ; OS call writes until null byte
mov r0,0            ; Define return code
swi OS_Exit         ; And exit.                               
Batteries not included, Some assembly required.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Wed Apr 03, 2013 7:26 pm

Hi dex,

What I want to do is, write numbers to stdout.

I think I can manage to convert the binary to a sequence of ascii character codes. I will prob push them onto a stack so I can pop them off in the right order.

The problem is that I can't work out how to print.

Can I load a number into r1 and have it print the character to the screen?

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Asm tuts

Wed Apr 03, 2013 8:43 pm

Hi antiloquax, yes you can, but you will need to use stack.
Here's a print char function example

Code: Select all

; Char function
format ELF executable
entry start
include 'ArmMacro.inc'
segment readable writeable executable

start:                                ;
        mov       r0, 5               ; number 5
        add       r0, 0x30            ; make ascii
        bl        PrintChar           ; call function
                                      ;
        mov       r0, 0ah             ; next line
        bl        PrintChar           ; call function

        mov       r0, 0x0             ; exit
        mov       r7, 0x1             ;
        swi       0x0                 ;

PrintChar:                            ;
        stmfd     sp!, {r0-r2, r7, lr}; save regs
        mov       r1, sp              ; use sp to point to r0
        mov       r0, 1               ; stdout
        mov       r2, r0              ; just one char
        mov       r7, 4               ; write
        swi       0                   ;
        ldmfd     sp!, {r0-r2, r7, pc}; restore regs
                                      ;
segment readable writeable            ;
Hope it helps and If you need more help just ask.
Batteries not included, Some assembly required.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Wed Apr 03, 2013 9:07 pm

Thanks DEXos, I will have a go with that tomorrow.
:D

coyotebush
Posts: 12
Joined: Fri Mar 01, 2013 7:39 pm

Re: Asm tuts

Wed Apr 03, 2013 10:20 pm

Being an old-time assembly programmer, I'll have to say nobody writes pure assembly any more. Instead, most code is written in "C" (or C++), and the critical pieces of assembly are written as "inlined assembly".

In applications, the main use of assembly is to access atomic operands (eg. test and set) or to optimize compression or encryption algorithms. Occasionally, an embedded application will implement a very low level I/O routine or a timing loop, but those don't work well from within a Linux environment where there are memory management issues, interrupts and DMA transfers.

At any rate, I'd vote for a tutorial on using ARM inline assembly rather than writing a complete assembly program.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Thu Apr 04, 2013 8:37 am

Thanks DEXos, that worked great (after a little tweaking because I am using gas).


I now have a program that can convert a .long to ascii chars!

thanks again.

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Asm tuts

Thu Apr 04, 2013 1:50 pm

@antiloquax, Glad you got it working.

@coyotebush, You are right to a point, but there's are some weird coders like myself, that like assembly as a programming language, we do not code in it because we think it will make our code faster, just by coding in it (unless we optimize it), but because we like the language and we want to learn how things work at a low level.

I mean in real terms what do people learn by, using per built lib and adding 10 lines of code ?.
You yourself know whats going on at a low level, because you have done assembly coding in the past.
But new coders may not know low level stuff and need to learn it, if they want to fully understand HLL.
Batteries not included, Some assembly required.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Thu Apr 04, 2013 3:09 pm

Yes - to echo what DEXos said, I am interested in doing some asm because I want to learn more about what is happening on the low level.

The rest of the time I am happy to use HLLs like Python, Scheme and Scala.

@ DEXos - can I just ask why we need to use the stack to set up those writes to stdout? Does the write process itself clobber the registers?

Here's what I have come up with for converting an integer into a series of ascii codes and printing them out (in the right order :roll: ).

I hope you don't mind me posting it here. If I have done something silly, I'd love some pointers.

Code: Select all

@ number.s
@ test program to print a number.

.section	.data

num:
	.long 123456791 

.globl	_start

_start:
	mov r0, $0xA		        @ load r0 with ascii newline code
	stmfd	sp!, {r0}		@ push onto stack
	adr r3, num		        @ load r3 with address of num
	ldr r4, [r3]		        @ load r4 with the number
	mov r5, $0 		        @ set counter to zero
loop:
	cmp r4, $9			@ if r4 <= 9 ...
	ble stackPush		@ branch ...
	sub r4, r4, $10		@ subtract 10 from r4
	add r5, r5, $1		        @ add one to counter
	bal loop			        @ back to top of loop


stackPush:
	add r0, r4, $0x30	        @ load r0 with r4 + 48
	stmfd	sp!, {r0}		@ push onto stack
	cmp r5, $0			@ if the counter is zero ...
	beq stackPull		        @ prepare to print
	mov r4, r5			@ load count into r4
	mov r5, $0			@ reset counter
	bal loop			        @ back to top of loop

stackPull:
	ldmfd sp!, {r0}		 @ pull from stack 
	bl PrintChar		         @ call print function
	cmp r0, $0xA		         @ was it a newline?
	beq exit			         @ if so exit
	bal stackPull		         @ otherwise get next char

exit:
	mov	r0, $0		        @ exit
	mov	r7, $1
	svc	$0


PrintChar:
	stmfd	sp!, {r0-r5, r7, lr}	@ push registers to stack
	mov	r1, sp			        @ use stack pointer 
	mov	r0, $1			        @ stdout
	mov	r2, r0			        @ one char
	mov	r7, $4			        @ write
	swi	$0
	ldmfd	sp!, {r0-r5, r7, pc}	@ restore registers

.end

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Asm tuts

Thu Apr 04, 2013 4:43 pm

Hi antiloquax, we do not need to use stack, its just convenient, as that function needs a pointer to the char or chars, not the chars them self, so you could for example do this

Code: Select all

; Char2 function
format ELF executable
entry start
include 'ArmMacro.inc'
segment readable writeable executable

start:  load_reg  r1, TheChar         ; load the address of TheChar into r1
        mov       r0, "5"             ; load the number char into r0
        Strb      r0,[r1]             ; load byte whats in r0 into address thats in r1
;note: r1 points to address TheChar still
        mov       r0, 1               ;
        mov       r2, r0              ;
        mov       r7, 4               ;
        swi       0                   ;
                                      ;
        mov       r0, 0x0             ; exit
        mov       r7, 0x1             ;
        swi       0x0                 ;
                                      ;
segment readable writeable            ;
                                      ;
TheChar db 0                          ; char var          

And use a var instead, but its simpler to use stack.
Batteries not included, Some assembly required.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Asm tuts

Tue Apr 09, 2013 10:26 am

Hi Dex,

Thanks for your help again. I've been playing around with my print a number code and I think I have a better understanding of the stack.

Blog post here.

I have been having a go at capturing input, but failing to get the code to move on once the user hits enter.
I'll look back over some of your examples as I think I have missed something obvious.
If you know of any helpful sites to look at I'd appreciate it, then I won't need to keep asking dumb questions here. :oops:

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Asm tuts

Tue Apr 09, 2013 3:15 pm

No ? is dumb, you want to learn so its natural you need answers.
First thing to note about learning, that others look down on.
Is to learn anything you need to COPY, its the only way to learn.
So find the code that's close to what you want and copy it, in this case its most likely to be for x86 linux, so convert it to arm.
If you study the code you will see that to port x86 linux assembly to linux arm assembly you will need to change the x86 reg to the arm reg, plus change the "int 80h" to "swi 0x0"

Once you got the code working, start moding and learning how it works.
Remember one big mistake many beginners make is that they thing they must know everything about how every bit of the code works.
That's how i was and i never learn't anything, it was not until i started to just make the code work anyway i could, including copying others work, that i started to learn.
You only learn by coding, not reading about coding, but by coding.
So first thing you need to do it watch these videos, there not about assembly, but about copying and learning
http://www.everythingisaremix.info/watch-the-series/

And this may help you with assembly:
http://asm.sourceforge.net/resources.html
Batteries not included, Some assembly required.

Return to “Other programming languages”