|
Prev: FASMLIB-0.8.0 is out
Next: keyboard/mouse programming
From: naunetr on 6 Dec 2007 15:28 hi all, i did this to convert LF sequence to CRLF from stdin to stdout. it appears to work okay. when cpu execute neg eax instruction is code below and eax is 0, will it remain unchanged? or it becomes -0? anything else i do in error? thanks. ; lf2crlf.asm - convert LF to CRLF; from stdin to stdout section .text global _start _start: mov ecx, buf ; address of read/write buffer mov edx, 0x01 ; bytes to read/write call do_read cmp eax, 0x0 ; success? jne short do_exit ; failed call do_write cmp eax, 0x0 je short _start ; loop again do_exit: mov eax, 0x01 ; syscall no. for exit mov ebx, esi ; load status code from esi int 0x80 do_read: mov eax, 0x03 ; syscall no. for read xor ebx, ebx ; read from fd 0 = stdin int 0x80 cmp eax, 0x01 ; success? jne short read_fail xor eax, eax ; ret. zero for sucess ret read_fail: neg eax ; 0 is unchanged(?) and -1 becomes 1 mov esi, eax inc eax ; return failure code ret do_write: mov eax, 0x04 ; syscall no. for write inc ebx ; write to fd 1 = stdout cmp byte [buf], 0x0a ; is byte LF? jne short call_write ; no, so output as is mov ecx, crlf ; yes, so output CRLF sequence inc edx ; write 2 bytes int 0x80 cmp eax, 0x02 ; success? jne short write_fail jmp short return call_write: int 0x80 cmp eax, 0x01 ; okay? jne short write_fail return: xor eax, eax ; success. so return 0 ret write_fail: mov esi, 0x01 ; failed. so return 1 mov eax, esi ; and also in eax ret section .data buf resb 0x01 crlf db 0x0d,0x0a
From: santosh on 6 Dec 2007 16:14 naunetr wrote: > hi all, > > i did this to convert LF sequence to CRLF from stdin to stdout. it > appears to work okay. when cpu execute neg eax instruction is code > below and eax is 0, will it remain unchanged? or it becomes -0? > anything else i do in error? thanks. > > ; lf2crlf.asm - convert LF to CRLF; from stdin to stdout > section .text > > global _start > > _start: > mov ecx, buf ; address of read/write buffer Maybe you can use a LEA instruction instead of a MOV here? lea ecx, [buf] > mov edx, 0x01 ; bytes to read/write > call do_read > cmp eax, 0x0 ; success? > jne short do_exit ; failed > call do_write > cmp eax, 0x0 > je short _start ; loop again > do_exit: > mov eax, 0x01 ; syscall no. for exit > mov ebx, esi ; load status code from esi > int 0x80 > do_read: > mov eax, 0x03 ; syscall no. for read > xor ebx, ebx ; read from fd 0 = stdin > int 0x80 > cmp eax, 0x01 ; success? > jne short read_fail > xor eax, eax ; ret. zero for sucess > ret > read_fail: > neg eax ; 0 is unchanged(?) and -1 becomes 1 > mov esi, eax Here you might want to do: xchg eax, esi > inc eax ; return failure code > ret > do_write: > mov eax, 0x04 ; syscall no. for write > inc ebx ; write to fd 1 = stdout > cmp byte [buf], 0x0a ; is byte LF? > jne short call_write ; no, so output as is > mov ecx, crlf ; yes, so output CRLF sequence Same as above. > inc edx ; write 2 bytes > int 0x80 > cmp eax, 0x02 ; success? > jne short write_fail > jmp short return > call_write: > int 0x80 > cmp eax, 0x01 ; okay? > jne short write_fail > return: > xor eax, eax ; success. so return 0 > ret > write_fail: > mov esi, 0x01 ; failed. so return 1 > mov eax, esi ; and also in eax > ret > > section .data > > buf resb 0x01 > crlf db 0x0d,0x0a I recommend placing 'crlf' in .rodata section. That will give the operating system license to place it in read only storage.
From: Frank Kotler on 7 Dec 2007 04:05 naunetr wrote: > hi all, > > i did this to convert LF sequence to CRLF from stdin to stdout. it > appears to work okay. when cpu execute neg eax instruction is code below > and eax is 0, will it remain unchanged? or it becomes -0? anything else > i do in error? Looks good to me, and appears to work. Great! I'm getting a warning from Nasm about the "resb" in section .data. Resb, resw, resd, resq, rest, and reso (I think that's all of 'em) should be used in an uninitialized section - .bss or a "custom" section with "nobits" set. In an initialized section "db 0" would be correct (or "times N db 0" for a bigger buffer). Nasm just bitches and zeros it, so it doesn't do any harm. Don't try to initialize data in .bss - Nasm will ignore it and you *won't* get what you want. > ; lf2crlf.asm - convert LF to CRLF; from stdin to stdout > section .text > > global _start > > _start: > mov ecx, buf ; address of read/write buffer > mov edx, 0x01 ; bytes to read/write Okay, by doing this prior to the call, you can reuse "do_read" to read a different number of bytes into a different buffer, if you want to. Good. (but then your error-checking locks you into one byte...) > call do_read > cmp eax, 0x0 ; success? > jne short do_exit ; failed > call do_write > cmp eax, 0x0 > je short _start ; loop again > do_exit: > mov eax, 0x01 ; syscall no. for exit > mov ebx, esi ; load status code from esi > int 0x80 > do_read: > mov eax, 0x03 ; syscall no. for read > xor ebx, ebx ; read from fd 0 = stdin > int 0x80 Reusable, so far. > cmp eax, 0x01 ; success? This locks you into using this routine for just one byte. Lemmee see... "cmp eax, edx" is no good... not an error to read less than we asked for. How about leaving "cmp eax, 1"... > jne short read_fail .... and making this "jl ..." (signed). That way, 0 (EOF) or an error (negative value) would jump, and "any number" would return success... > xor eax, eax ; ret. zero for sucess > ret Okay... > read_fail: > neg eax ; 0 is unchanged(?) and -1 becomes 1 > mov esi, eax Okay... you want to return the positive error number - from the program, for "echo $?", not just from this routine - right? The error numbers are defined as positive integers, but what we see in eax (if there's an error) is the negative of that number. But if eax was zero, we just want to return some non-zero value from this routine... but zero from the program. Right? > inc eax ; return failure code > ret Neat! > do_write: > mov eax, 0x04 ; syscall no. for write > inc ebx ; write to fd 1 = stdout > cmp byte [buf], 0x0a ; is byte LF? > jne short call_write ; no, so output as is > mov ecx, crlf ; yes, so output CRLF sequence > inc edx ; write 2 bytes > int 0x80 > cmp eax, 0x02 ; success? > jne short write_fail > jmp short return > call_write: > int 0x80 > cmp eax, 0x01 ; okay? > jne short write_fail > return: > xor eax, eax ; success. so return 0 > ret > write_fail: > mov esi, 0x01 ; failed. so return 1 > mov eax, esi ; and also in eax > ret > > section .data > > buf resb 0x01 > crlf db 0x0d,0x0a Pretty good! I have a tough time finding anything to complain about. Best, Frank
From: Frank Kotler on 7 Dec 2007 04:33 santosh wrote: > naunetr wrote: > > >>hi all, >> >>i did this to convert LF sequence to CRLF from stdin to stdout. it >>appears to work okay. when cpu execute neg eax instruction is code >>below and eax is 0, will it remain unchanged? or it becomes -0? >>anything else i do in error? thanks. >> >>; lf2crlf.asm - convert LF to CRLF; from stdin to stdout >>section .text >> >>global _start >> >>_start: >> mov ecx, buf ; address of read/write buffer > > > Maybe you can use a LEA instruction instead of a MOV here? > > lea ecx, [buf] Sure he can. What does it gain him? (but a byte) >> mov edx, 0x01 ; bytes to read/write >> call do_read >> cmp eax, 0x0 ; success? >> jne short do_exit ; failed >> call do_write >> cmp eax, 0x0 >> je short _start ; loop again >>do_exit: >> mov eax, 0x01 ; syscall no. for exit >> mov ebx, esi ; load status code from esi >> int 0x80 >>do_read: >> mov eax, 0x03 ; syscall no. for read >> xor ebx, ebx ; read from fd 0 = stdin >> int 0x80 >> cmp eax, 0x01 ; success? >> jne short read_fail >> xor eax, eax ; ret. zero for sucess >> ret >>read_fail: >> neg eax ; 0 is unchanged(?) and -1 becomes 1 >> mov esi, eax > > > Here you might want to do: > > xchg eax, esi Why? What's in esi? If it were 0FFFFFFFFh, what would we be returning? >> inc eax ; return failure code >> ret >>do_write: >> mov eax, 0x04 ; syscall no. for write >> inc ebx ; write to fd 1 = stdout >> cmp byte [buf], 0x0a ; is byte LF? >> jne short call_write ; no, so output as is >> mov ecx, crlf ; yes, so output CRLF sequence > > > Same as above. What? *Another* byte? :) >> inc edx ; write 2 bytes >> int 0x80 >> cmp eax, 0x02 ; success? >> jne short write_fail >> jmp short return >>call_write: >> int 0x80 >> cmp eax, 0x01 ; okay? >> jne short write_fail >>return: >> xor eax, eax ; success. so return 0 >> ret >>write_fail: >> mov esi, 0x01 ; failed. so return 1 >> mov eax, esi ; and also in eax >> ret >> >>section .data >> >> buf resb 0x01 >> crlf db 0x0d,0x0a > > > I recommend placing 'crlf' in .rodata section. That will give the > operating system license to place it in read only storage. That might not be a bad idea. The "resb" should be in a .bss section - Nasm whines about it. Adding sections adds bloat to the header. I might put the crlf in .text - to make it readonly, and the buffer in .bss - eliminate .data entirely. Really isn't going to gain a lot, I don't think...
From: Wolfgang Kern on 7 Dec 2007 07:42
"naunetr" asked: > ... when cpu execute neg eax instruction is code below and eax is 0, > will it remain unchanged? or it becomes -0? The CPU don't know a negative Zero, only the FPU can have this. NEG (in opposition to NOT) does a 2's complement: xor eax,ffffffffh ;toggle all bits w/o flags update; same as NOT add eax,1 ;so a zero will remain, but flags are altered if eax was 0 then Z,Ov,Ac,Cy will be set and Sf is reset. __ wolfgang |