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"