From: naunetr on
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
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
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
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

"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



 |  Next  |  Last
Pages: 1 2
Prev: FASMLIB-0.8.0 is out
Next: keyboard/mouse programming