Author Topic: ASCII contents of file  (Read 21388 times)

Offline Manasi

  • Jr. Member
  • *
  • Posts: 9
ASCII contents of file
« on: October 05, 2013, 01:11:50 PM »
The following code displays the contents of file in their equivalent hex value. Can anyone help me to display the ASCII equivalent of the contents?
Code: [Select]
SECTION .data
file_name db 'abc.txt'

SECTION .bss
fd_in resd 1
temp resb 250
filecontent resb 250
fbuff_len equ $-filecontent


SECTION .text
global _start
_start:
mov eax,5 ;open a file
mov ebx,file_name
mov ecx,0
mov edx,777
int 80h

mov dword[fd_in],eax

mov eax,3 ;read from file
mov ebx,[fd_in]
mov ecx,filecontent
mov edx,fbuff_len
int 80h

mov edi,temp
mov esi,filecontent
mov dh,25
nextnum: mov dl,2

mov al,byte[esi]


dispnum: rol al,4
mov bl,al
and al,0fh
add al,30h
mov byte[edi],al
inc edi
mov al,bl
dec dl
jnz dispnum
inc esi
dec dh
jnz nextnum


mov eax,4
mov ebx,1
mov ecx,temp
mov edx,250
int 80h

mov eax,6
mov ebx,[fd_in]
int 80h

mov eax,1
mov ebx,0
int 80h
Thanks in advance
Regards,
Manasi
« Last Edit: October 05, 2013, 01:17:05 PM by Frank Kotler »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: ASCII contents of file
« Reply #1 on: October 05, 2013, 02:20:09 PM »
Hi Manasi,

I put "code tags" around your code (just the word "code" in square brackets and "/code" at the end of it). Arguably makes it easier to read, and definitely makes it easier to download. Then I downloaded it. :)

Can't say that it really worked very well. In the first place, there was no "abc.txt" (until I created it). No matter, even though the sys_open failed, your program continued. This is not ideal! Really should "issue a diagnostic" and "exit gracefully" (or retry) aka "scream and die". I added a "quick and dirty" check and just exited if the sys_open failed.

Then... you don't really display hex. Worked okay for '0' through '9', but 'A'  through 'F' came out garbled. I fixed that, too. And I limited output to the actual length that we read. There are other things that could be improved... You're going to need two hex digits for each byte/character read, so the "temp" buffer should be twice as long. Well... it's a start...

Code: [Select]
SECTION .data
file_name db 'abc.txt'

SECTION .bss
fd_in resd 1
temp resb 250
filecontent resb 250
fbuff_len equ $-filecontent
length_read resd 1


SECTION .text
global _start
_start:
mov eax,5 ;open a file
mov ebx,file_name
mov ecx,0
mov edx,777
int 80h

; did open succeed?
test eax, eax
js exit


mov dword[fd_in],eax

mov eax,3 ;read from file
mov ebx,[fd_in]
mov ecx,filecontent
mov edx,fbuff_len
int 80h
; eax has length actually read
mov [length_read], eax

mov edi,temp
mov esi,filecontent
mov dh,25
nextnum: mov dl,2

mov al,byte[esi]


dispnum: rol al,4
mov bl,al
and al,0fh
add al,30h
cmp al, '9'
jbe dec_digit
add al, 7
dec_digit:
mov byte[edi],al
inc edi
mov al,bl
dec dl
jnz dispnum
inc esi
dec dh
jnz nextnum


mov eax,4
mov ebx,1
mov ecx,temp
mov edx,[length_read]
shl edx, 1 ; two bytes of hex for each character read
int 80h

mov eax,6
mov ebx,[fd_in]
int 80h

exit:
mov eax,1
mov ebx,0
int 80h

To display "ASCII equivalent", just sys_write the file... or perhaps I don't understand the question...

Best,
Frank


Offline Manasi

  • Jr. Member
  • *
  • Posts: 9
Re: ASCII contents of file
« Reply #2 on: October 05, 2013, 02:33:24 PM »
Frank,

Thank you for the help
 hex equivalent means it shows that if file abc.txt has 'a' then it displays 61
b=62
A=41
B=42
and so on
what i wanted to know is how do i display the ASCII equivalent i.e.
A=65
B=66
and so on for all the content in the file.

I would really appreciate if  you could help me out with this.

Thanks again,
Regards,
Manasi

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: ASCII contents of file
« Reply #3 on: October 05, 2013, 03:55:00 PM »
Maybe something like this?

Code: [Select]
; display characters and hex ascii codes from a file
;
; nasm -f elf32 myfile.asm
; ld -o myfile myfile.o -melf_i386

SECTION .data
    file_name db 'abc.txt'

SECTION .bss
    fd_in resd 1
    filecontent resb 250
    fbuff_len equ $-filecontent
    length_read resd 1


SECTION .text
global _start
_start:
    mov eax,5 ;open a file
    mov ebx,file_name
    mov ecx,0
    mov edx,777
    int 80h

; did open succeed?
    test eax, eax
    js exit


    mov dword[fd_in],eax

    mov eax,3 ;read from file
    mov ebx,[fd_in]
    mov ecx,filecontent
    mov edx,fbuff_len
    int 80h
; eax has length actually read
    mov [length_read], eax

    mov esi,filecontent

; point edi to end of file
    mov edi, esi
    add edi, [length_read]

nextnum:
    mov dl,2 ; count for hex digits

    mov al,byte[esi]

    call putc
    push eax
    mov al, '='
    call putc
    pop eax


dispnum:
    rol al,4
    mov bl,al
    and al,0fh
    add al,30h

    cmp al, '9'
    jbe dec_digit
    add al, 7
dec_digit:
    call putc

    mov al,bl
    dec dl
    jnz dispnum
    mov al, 'h'
    call putc
    mov al, 10 ; linefeed
    call putc

    inc esi
    cmp esi, edi
jnz nextnum

    mov eax,6 ; __NR_close
    mov ebx,[fd_in]
    int 80h

; pretend no error
    xor eax, eax

exit:
    mov ebx, eax ; possible error number in ebx
    neg ebx  ; negate it for easier reading with "echo $?"
    mov eax,1
    int 80h

;---------------------------
; print character in al
putc:
    push edx
    push ecx
    push ebx
    push eax ;this serves as our buffer

    mov ecx, esp ; buffer
    mov edx, 1 ; just 1
    mov ebx, 1 ; stdout
    mov eax, 4 ; __NR_write
    int 80h

    pop eax
    pop ebx
    pop ecx
    pop edx
    ret
;------------------------------

Really would have been better to put all this stuff in a buffer and print it all in one system call rather than call system for every single character. This was easy.

Best,
Frank


Offline Manasi

  • Jr. Member
  • *
  • Posts: 9
Re: ASCII contents of file
« Reply #4 on: October 05, 2013, 04:24:29 PM »
Frank,
The program works successfully but i still havent got how do i display the ASCII values. let me give an example
my file 'abc.txt' has the following contents:
ABCD

so my output should be
65666768

but what it is showing are the hex values
i.e 41424344 and so on

So basically i need to Display ASCII so that i get the desired output
But i am unable to do that.
Please help me.

Thanks again
Regards,
Manasi

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: ASCII contents of file
« Reply #5 on: October 05, 2013, 05:28:49 PM »
Do I understand that you want to represent the ascii codes as decimal? (why? hex is much more civilized!) Well, okay...  this is crude, but I think it does what you want...

Code: [Select]
; display characters and decimal ascii codes from a file
;
; nasm -f elf32 myfile.asm
; ld -o myfile myfile.o -melf_i386

SECTION .data
    file_name db 'abc.txt'

SECTION .bss
    fd_in resd 1
    filecontent resb 250
    fbuff_len equ $-filecontent
    length_read resd 1


SECTION .text
global _start
_start:
    mov eax,5 ;open a file
    mov ebx,file_name
    mov ecx,0
    mov edx,777
    int 80h

; did open succeed?
    test eax, eax
    js exit


    mov dword[fd_in],eax

    mov eax,3 ;read from file
    mov ebx,[fd_in]
    mov ecx,filecontent
    mov edx,fbuff_len
    int 80h
; eax has length actually read
    mov [length_read], eax

    mov esi,filecontent

; point edi to end of file
    mov edi, esi
    add edi, [length_read]

    xor eax, eax ; just to make sure upper bytes are clear
nextnum:
    mov al,byte[esi]

    call putc
    push eax
    mov al, '='
    call putc
    pop eax


dispnum:
    call showeaxd
    mov al, 10 ; linefeed
    call putc

    inc esi
    cmp esi, edi
jnz nextnum

    mov eax,6 ; __NR_close
    mov ebx,[fd_in]
    int 80h

; pretend no error
    xor eax, eax

exit:
    mov ebx, eax ; possible error number in ebx
    neg ebx  ; negate it for easier reading with "echo $?"
    mov eax,1
    int 80h

;---------------------------
; print character in al
putc:
    push edx
    push ecx
    push ebx
    push eax ;this serves as our buffer

    mov ecx, esp ; buffer
    mov edx, 1 ; just 1
    mov ebx, 1 ; stdout
    mov eax, 4 ; __NR_write
    int 80h

    pop eax
    pop ebx
    pop ecx
    pop edx
    ret
;------------------------------

;---------------------------------
; showeaxd - print a decimal representation of eax to stdout
; for "debug purposes only"... mostly
; expects: number in eax
; returns; nothing useful
showeaxd:
    push eax
    push ebx
    push ecx
    push edx
    push esi
   
    sub esp, 10h
    lea ecx, [esp + 12]
    mov ebx, 10
    xor esi, esi
   
.top:   
    dec ecx
    xor edx, edx
    div ebx
    add dl, '0'
    mov [ecx], dl
    inc esi
    or eax, eax
    jnz .top
   
    mov edx, esi
    mov ebx, 1
    mov eax, 4
    int 80h
   
    add esp, 10h

    pop esi
    pop edx
    pop ecx
    pop ebx
    pop eax

    ret
;---------------------------------

Best,
Frank


Offline Manasi

  • Jr. Member
  • *
  • Posts: 9
Re: ASCII contents of file
« Reply #6 on: October 05, 2013, 05:40:53 PM »
Frank,

Thanks a ton for the help.
This is what I exactly wanted.
Thanks again!!!! :) :D

Regards,
Manasi

Offline Manasi

  • Jr. Member
  • *
  • Posts: 9
Re: ASCII contents of file
« Reply #7 on: October 20, 2013, 03:47:40 PM »
Frank,
In the last code could you please explain the logic for the function showeaxd.
I mean how does the program show the decimal representation.

Thanks,
Regards,
Manasi

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: ASCII contents of file
« Reply #8 on: October 20, 2013, 07:02:04 PM »
Code: [Select]
;---------------------------------
; showeaxd - print a decimal representation of eax to stdout
; for "debug purposes only"... mostly
; expects: number in eax
; returns; nothing useful
showeaxd:

; save all registers used
; this is "overkill" - a "C-style" function would expect ecx and edx
; to be trashed and the "result" returned in eax
; since I don't return anything, and might be using ecx/edx
; I saved everything, "for convenience"

    push eax
    push ebx
    push ecx
    push edx
    push esi

; make a buffer on the stack
; a 32-bit number could be up to 10 digits
; we might want a terminating 0  - or perhaps a linefeed
; we might want space for a minus sign
; 16 bytes is just a "nice round number" - rather arbitrary

    sub esp, 10h

; since "div" is going to give us our remainders - our digits - in the "wrong" order
; we want to start at the "end" (higher memory) of the buffer and work backwards
; towards the beginning of the buffer (lower memory)
;
; since sys_write is going to expect the buffer address in ecx
; I use ecx as the buffer pointer throughout
; the 12 is, again, rather arbitrary

    lea ecx, [esp + 12]

; we're going to want to divide by 10

    mov ebx, 10
 
; since sys_write expects the count in edx, I'd use edx...
; but "div" is using edx (!) so I need another digit counter

   xor esi, esi
 
; at this point, I sometimes modify this function to add a linefeed "after" the number
; if you wanted a zero-terminated string you could do it here
; this explains why I move to next position first thing in my loop...
   
.top:   

; move to next position "backwards" in buffer

    dec ecx

; "div" divides edx:eax by what you say (32-bit parameter)
; and puts the quotient in eax and the remainder in edx
; if the quotient won't fit in eax, it throws an exception, crashing our program
; the CPU doesn't ignore edx, so we can't either (common newbie error!)
; we want it zero!

    xor edx, edx
    div ebx

; quotient in eax, remainder in edx
; we know the remainder is between 0 and 9 so it'll all fit in dl
; we want to "convert" the number to the ascii character representing that number
; adding 30h or 48 decimal or the character '0' will do it

    add dl, '0'

; and stuff it in the buffer

    mov [ecx], dl

; and count it

    inc esi

; quotient is still in eax - is it zero?
; usually I use "test" here, I don''t know why I used "or"
; the idea is to set the flags without altering eax
; you could just "cmp eax, 0"

    or eax, eax

; if quotient isn't zero, do it again

    jnz .top

; now we just print the buffer using sys_write - ecx is all set
; move our count into edx
   
    mov edx, esi
    mov ebx, 1 ; stdout
    mov eax, 4 ; __NR_write
    int 80h ; ask the kernel to make it so

; we're done with our buffer, make it go away
   
    add esp, 10h

; restore callers regs

    pop esi
    pop edx
    pop ecx
    pop ebx
    pop eax

; click your heels together and say "there's no place like home"

    ret
;---------------------------------

I don't know if that answers your question. We can break it down further if need be.

Best,
Frank


Offline Manasi

  • Jr. Member
  • *
  • Posts: 9
Re: ASCII contents of file
« Reply #9 on: October 21, 2013, 12:35:44 AM »
Frank,

Thank you for explaining the logic of the function. It did explain what i had not understood.

Thanks,
Regards,
Manasi