* [9fans] ASCII character conversion program in assembler
@ 2013-02-07 13:12 Alexander Kapshuk
2013-02-07 21:02 ` Anthony Martin
0 siblings, 1 reply; 2+ messages in thread
From: Alexander Kapshuk @ 2013-02-07 13:12 UTC (permalink / raw)
To: Fans of the OS Plan 9 from Bell Labs
The program below, which I'm writing for educational purposes, is
intended to read a steam of ASCII characters on STDIN, convert any
lowercase character to its uppercase equivalent, and print the
resulting character on STDOUT. Any advice would be appreciated.
-------------------------------------------
#define OPEN 14
#define CREATE 22
#define PREAD 50
#define PWRITE 51
#define CLOSE 4
#define EXITS 8
#define SYSCALL 64
#define OREAD 0
#define OWRITE_OTRUNC 17
#define EOF 0
#define RWRWR 436 //0664 file permissions
#define BUF_SIZE 500
#define UPCONV 32
#define LCA 'a'
#define LCZ 'z'
#define STDIN 0
#define STDOUT 1
GLOBL buf+0(SB),$BUF_SIZE // store in bss ?
TEXT _main+0(SB),$0
CALL main+0(SB)
TEXT main+0(SB),$0
start_read_lp:
MOVL $STDIN,4(SP)
MOVL $buf+0(SB),8(SP)
MOVL $BUF_SIZE,12(SP)
MOVL $PREAD,AX
INT $SYSCALL
CMPL AX,$EOF
JLE end_lp
MOVL $buf+0(SB),(SP)
MOVL AX,4(SP)
CALL conv2up+0(SB)
MOVL $STDOUT,4(SP)
MOVL $buf+0(SB),8(SP)
MOVL AX,12(SP)
MOVL $-1,16(SP)
MOVL $-1,20(SP)
MOVL $PWRITE,AX
INT $SYSCALL
JMP start_read_lp
end_lp:
MOVL $EXITS,AX
INT $SYSCALL
TEXT conv2up+0(SB),0,$0
MOVL buf+0(FP),AX
MOVL bufsiz+4(FP),DX
XORL $0,CX
CMPL DX,$0
JEQ end_conv_lp
conv_lp:
MOVB (AX)(CX*1),BL
CMPB BL,$LCA // this and next instruction return true and
JLT next_byte // execution goes to next_byte.
CMPB BL,$LCZ
JGT next_byte
SUBB $UPCONV,BL
MOVB BL,(AX)(CX*1)
next_byte:
INCL CX
CMPL CX,DX
JNE conv_lp
end_conv_lp:
RET
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [9fans] ASCII character conversion program in assembler
2013-02-07 13:12 [9fans] ASCII character conversion program in assembler Alexander Kapshuk
@ 2013-02-07 21:02 ` Anthony Martin
0 siblings, 0 replies; 2+ messages in thread
From: Anthony Martin @ 2013-02-07 21:02 UTC (permalink / raw)
To: Fans of the OS Plan 9 from Bell Labs
[-- Attachment #1: Type: text/plain, Size: 1188 bytes --]
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
[-- Attachment #2: conv.s --]
[-- Type: text/plain, Size: 1713 bytes --]
#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"
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-02-07 21:02 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-07 13:12 [9fans] ASCII character conversion program in assembler Alexander Kapshuk
2013-02-07 21:02 ` Anthony Martin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).