how to debug an NASM assembly program requiring user input?
Asked Answered
E

2

6

I'm going through jeff's amazing book assembly step by step, and I am on chapter 8 where he shows an example of an assembly program that takes a file from the user this way:

SECTION .bss            ; Section containing uninitialized data

    BUFFLEN equ 1024    ; Length of buffer
    Buff:   resb BUFFLEN    ; Text buffer itself

it reads the file text into Buff, and outputs a version of that text in ALL CAPS to a different file.

I want to run this program in debug mode to step through it to analyze what is happening with all the registers.

I am running this on ubuntu with INSIGHT.

I am a complete beginner. I know how to use Insight to step through, but the way the user needs to run this program is:

myProgram > outputfile.txt < inputfile.txt

How do I mimic this in a debugger?

here's the full source:

;  Executable name : uppercaser2
;  Version         : 1.0
;  Created date    : 3/25/2009
;  Last update     : 3/25/2009
;  Author          : Jeff Duntemann
;  Description     : A simple program in assembly for Linux, using NASM 2.05,
;    demonstrating simple text file I/O (through redirection) for reading an
;    input file to a buffer in blocks, forcing lowercase characters to 
;    uppercase, and writing the modified buffer to an output file.
;
;  Run it this way:
;    uppercaser2 > (output file) < (input file)  
;
;  Build using these commands:
;    nasm -f elf -g -F stabs uppercaser2.asm
;    ld -o uppercaser2 uppercaser2.o
;
SECTION .bss            ; Section containing uninitialized data

    BUFFLEN equ 1024    ; Length of buffer
    Buff:   resb BUFFLEN    ; Text buffer itself

SECTION .data           ; Section containing initialised data

SECTION .text           ; Section containing code

global  _start          ; Linker needs this to find the entry point!

_start:
    nop         ; This no-op keeps gdb happy...

; Read a buffer full of text from stdin:
read:
    mov eax,3       ; Specify sys_read call
    mov ebx,0       ; Specify File Descriptor 0: Standard Input
    mov ecx,Buff        ; Pass offset of the buffer to read to
    mov edx,BUFFLEN     ; Pass number of bytes to read at one pass
    int 80h         ; Call sys_read to fill the buffer
    mov esi,eax     ; Copy sys_read return value for safekeeping
    cmp eax,0       ; If eax=0, sys_read reached EOF on stdin
    je Done         ; Jump If Equal (to 0, from compare)

; Set up the registers for the process buffer step:
    mov ecx,esi     ; Place the number of bytes read into ecx
    mov ebp,Buff        ; Place address of buffer into ebp
    dec ebp         ; Adjust count to offset

; Go through the buffer and convert lowercase to uppercase characters:
Scan:
    cmp byte [ebp+ecx],61h  ; Test input char against lowercase 'a'
    jb Next         ; If below 'a' in ASCII, not lowercase
    cmp byte [ebp+ecx],7Ah  ; Test input char against lowercase 'z'
    ja Next         ; If above 'z' in ASCII, not lowercase
                ; At this point, we have a lowercase char
    sub byte [ebp+ecx],20h  ; Subtract 20h to give uppercase...
Next:   dec ecx         ; Decrement counter
    jnz Scan        ; If characters remain, loop back

; Write the buffer full of processed text to stdout:
Write:
    mov eax,4       ; Specify sys_write call
    mov ebx,1       ; Specify File Descriptor 1: Standard output
    mov ecx,Buff        ; Pass offset of the buffer
    mov edx,esi     ; Pass the # of bytes of data in the buffer
    int 80h         ; Make kernel call
    jmp read        ; Loop back and load another buffer full

; All done! Let's end this party:
Done:
    mov eax,1       ; Code for Exit Syscall
    mov ebx,0       ; Return a code of zero 
    int 80H         ; Make kernel call
Eliza answered 2/11, 2012 at 22:30 Comment(10)
Easiest thing is probably to not redirect stdin/stdout - just type in some text to convert...Compte
Considering that Insight is an old unsupported GDB frontend, I suggest you learn good old console GDB. It's the most powerful you'll get.Hedgepeth
@Hedgepeth thank you, can you suggest how this can be done in gdb? ive never used itEliza
@FrankKotler can you please show me what you mmean?Eliza
@FrankKotler does anything need to be clarified?Eliza
I don't have the time to, just look for a good tutorial on GDB.Hedgepeth
@Hedgepeth can you suggest a place to start?Eliza
Yes. Compile your program into an ELF executable with NASM that has debugging symbols, and then type gdb myprog. Then look for a tutorial on GDB and how to give input to the program.Hedgepeth
thanks! that might help. i will come back and ask you more q's after i've followed your adviceEliza
Sure. Glad to help, and sorry I couldn't give a complete answer.Hedgepeth
T
3

It sounds like you want to attach the proccess to GDB. You could try this.

shell$ gdb ./uppercaser2
  gdb> list
  gdb> break read
  gdb> run > ouput.txt < input.txt
  gdb> x/5i $eip

At the shell prompt you start GDB and attach uppercaser2 to GDB. The debugging symbols should load and you can check by using list to display your source. Make a breakpoint at your desired location by line number or function name. use GDB's run to start the program with your input and ouput files. From here, you can analyze the registers and step through memory using GDB commands.

Terpsichore answered 6/11, 2012 at 5:51 Comment(1)
For me, gdb outputs: (No debugging symbols found in ./hello) where hello is the file I compiled from hello.asm Is there a way to pass a parameter (like -g in C++ and C) while compiling Assembly so that the debugging symbols exist?Dobb
R
0

At the run command, you set the user input like this:

shell$ gdb ./executable  
gdb> break main  
gdb> run user input  
Raquel answered 28/4, 2014 at 15:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.