I have a few suggestions and corrections.
1. You have to actually allocate space for your local variables.
This means either calculating how much space you'll need and
annotating the TEXT pseudo-instruction or decrementing the SP
as you go.
2. Calls into the kernel must look like normal calls. When writing
in C, libc takes care of this for you. In assembly you have to
do it yourself. There are two ways to do this: define a procedure
and call it or push a fake return address onto the stack. I see
you've chosen the latter but the former would make the code read
nicer.
3. There's no need to but the buffer in the data section. It can
be a local variable. See point 2.
4. The pread(2) system call takes a 64-bit offset like pwrite(2).
5. There's no need to define a procedure called main. The linker
doesn't care as long as your code starts at _main.
6. Since you're using the address of the buffer quite frequently,
your program will read better if you store it in a register.
7. It helps to pass informative error strings to exits(2).
I've attached a program that accomplishes the same task.
Cheers,
Anthony
#define STDIN 0
#define STDOUT 1
#define EOF 0
#define BUFSIZE 4096
#define BUFOFFSET 20
#define SYS_EXITS 8
#define SYS_PREAD 50
#define SYS_PWRITE 51
TEXT _main(SB),$(BUFSIZE+BUFOFFSET)
LEAL BUFOFFSET(SP), SI
read:
// read into the buffer from stdin.
MOVL $STDIN, 0(SP)
MOVL SI, 4(SP)
MOVL $BUFSIZE, 8(SP)
MOVL $-1, 12(SP)
MOVL $-1, 16(SP)
CALL pread(SB)
CMPL AX, $EOF
JLE exit
// call conv to transform lowercase ASCII to uppercase.
MOVL SI, 0(SP)
MOVL AX, 4(SP)
CALL conv(SB)
// write the potentially modified buffer to stdout.
MOVL $STDOUT, 0(SP)
MOVL SI, 4(SP)
MOVL AX, 8(SP)
MOVL $-1, 12(SP)
MOVL $-1, 16(SP)
CALL pwrite(SB)
CMPL AX, 8(SP)
JEQ read
MOVL $writefail<>(SB), 0(SP)
CALL exits(SB)
exit:
JEQ 3(PC)
MOVL $readfail<>(SB), 0(SP)
CALL exits(SB)
MOVL $0, 0(SP)
CALL exits(SB)
RET
// void conv(char *buf, int n)
TEXT conv(SB), $0
MOVL buf+0(FP), SI
MOVL n+4(FP), AX
MOVL $0, CX
CMPL CX, AX
JGE done
loop:
MOVB (SI)(CX*1), BL
CMPB BL, $'a'
JLT 5(PC)
CMPB BL, $'z'
JGT 3(PC)
SUBB $0x20, BL
MOVB BL, (SI)(CX*1)
INCL CX
CMPL CX, AX
JLT loop
done:
RET
// void exits(char *status)
TEXT exits(SB),$0
MOVL $SYS_EXITS, AX
INT $64
RET
// int pread(int fd, char *buf, int n, vlong off)
TEXT pread(SB),$0
MOVL $SYS_PREAD, AX
INT $64
RET
// int pwrite(int fd, char *buf, int n, vlong off)
TEXT pwrite(SB),$0
MOVL $SYS_PWRITE, AX
INT $64
RET
GLOBL readfail<>(SB),$13
DATA readfail<>+0(SB)/8, $"read fai"
DATA readfail<>+8(SB)/5, $"lure\z"
GLOBL writefail<>(SB),$14
DATA writefail<>+0(SB)/8, $"write fa"
DATA writefail<>+8(SB)/6, $"ilure\z"