Alpha assembler, syscalls

HHunt

Supreme [H]ardness
Joined
Apr 12, 2001
Messages
6,063
This might technically be "programming", but I think it fits better here. Anyway.
I've been playing with basic assembler syscalls in FreeBSD and linux. It's relatively simple on x86:
Code:
Linux style:
eax contains the syscall number, ebx, ecx, edx the arguments

.data                       ; data part starts here
hello:                      ; "hello" is the address here
        .string "Morn\n"    ; The data
        length = . - hello  ; Length (. means "here")

.text                       ; code starts here
.global _start              ; _start is an ELF convention
_start:
        movl $4, %eax       ; syscall number 4 is write
        movl $1, %ebx       ; 1st arg: file descriptor (1 is stdout)
        movl $hello, %ecx   ; 2nd arg: address to string
        movl $length, %edx  ; 3rd arg: length of string
        int $0x80           ; Generate an interrupt to call the kernel

        movl $1, %eax       ; syscall number 1 is exit
        movl $0, %ebx       ; 1st argument: return value
        int $0x80           ; do the syscall


BSD style:
eax contains the syscall number, arguments pushed onto the stack.
The topmost item is ignored (it's usually a return address).
The first argument is pushed last, so it's on top.

.data
hello:
        .string "Morn\n"
        length = . - hello

.text
.global _start
_start:
        movl $4, %eax   ; syscall 4 is write
        push $length    ; 3rd arg: length
        push $hello     ; 2nd arg: addr to string
        push $1         ; 1st arg: file desc, 1 is stdout
        push $0         ; discarded
        int $0x80       ; *blam*

        movl $1, %eax   ; syscall 1 is exit
        push $0         ; return value
        push $0         ; discarded
        int $0x80       ; go for it

This is GNU as syntax, x86-style. Both work. My problem is: How the fsck(8) do you do this on alpha (AXP)? Just for fun the syntax for as on alpha and x86 is utterly different. For extra joy, I can't find anything like push and pop for stack handling on the alpha, either.

From what I can find, I suspect you put the syscall-number in $0 ($v0), the arguments in $16 and onwards ($a0, $a1, etc.), and possibly do a call_pal 0x83 (or 0x80?) to do it. Perhaps. It keeps pagefaulting no matter how I write it, though. So, does anyone here know any relevant alpha assembler?
 
Some intense reading of Tru64-documentation for assembler programmers later (here), I've got it.

TFM said:
2 If you are writing a procedure that references static storage, calls other procedures, uses constants greater than 31 bits in size, or uses floating constants, you must load the $gp register with the global pointer value for the procedure:

ldgp $gp,0($27)

Register $27 contains the procedure value (the address of this procedure as supplied by the caller).

This works:
Code:
; This does the same as the following C code, and is comparably correct:
; main() { write(1, "Hi, folks\n", 11); }
; (In other words, very dirty, but working.)

.data
hello:
        .string "Hello, [H]\n"
        length = . - hello

.text
.global _start
_start:
        ldgp $gp, 0($27)         ; Magic :)

        ldiq    $16,    1        ; 1st arg: file descriptor (1 is stdout)
        lda     $17,    hello    ; 2nd arg: address of string
        ldiq    $18,    length   ; 3rd arg: length of string
        ldiq    $0,     4        ; syscall number 4: write
        call_pal 0x83            ; do a syscall (0x83 is PAL_callsys)

        ldiq $0, 1               ; syscall 1 is exit
        mov  $16, $31            ; return value ($31 is 0)
        call_pal 0x83            ; syscall

An ultrashort introduction to alpha assembler:
It's 64-bit. Use quadwords (8 bytes) if in doubt.
$n is a register. There's 32 of them, for assorted uses. $16 -> $21 can be used for arguments. $gp is $29. $31 always contains 0.
N($r) means "the data N bytes after the address in $r".
The form is " command destination, source/value".
ldiq is "load immediate quadword", and puts a static value into a register.
lda is "load address".


</thread>, unless someone has anything to add or ask.
 
Interesting that the Alpha has 32 GP registers, yet even the brand-new AMD64 architecture only implements 16. ;)

Your problem looks interesting - congrats on getting your code working. :cool:
 
Different design philosophies. Alpha's a RISC architecture, x86 is CISC. While the distinction's gotten fuzzy with RISC archs growing larger and x86 chips translating the CISC code into an internal RISC language, the big difference is that RISC chips have a 'load/store' design. This means that all data must be loaded into a register to be operated on & then stored back to memory. x86, OTOH, allows instructions to read/write arguments in main memory.

Of course, this doesn't mean that people haven't been complaining about the lack of general purpose registers on x86 since... well... it came out.
 
Josh_B said:
Interesting that the Alpha has 32 GP registers, yet even the brand-new AMD64 architecture only implements 16. ;)

Your problem looks interesting - congrats on getting your code working. :cool:


Thanks. :)
The next part is porting a cgi program a guy in my class wrote from x86 to alpha, I think. Not really useful, but interesting.
 
Back
Top