2

I'm writing an assembly program in NASM and as part of it I wanna be able to read command line arguments, which in my case could me one of two things, a debug message "-d", or a number represented in Hex, so for example:

`./programName AF -d` 

The thing is when I use pop the first argument off the stack that's not the argc or programName, it's suppose to be a string representing say that HEX number, and I try to process it byte byte eventually ending up with a segfault. Here's my attempt:

main:
push ebp
mov ebp, esp

mov ecx, [ebp +8]      ;argc
mov eax, [ebp + 16]    ; first arg that was put in by the user
dec ecx                ; update num of "real" args

.nextArg:
    cmp ecx, 0
    je .noMoreArgs
    push eax
    call process_arg
    add esp, 4
    dec ecx
    jmp .nextArg
.noMoreArgs:
 ...

process_arg function: (capacity is a variable in memory to indicate capacity in btyes of an allocated stack, debugStr is a string for the purpose of the comparison)

push ebp
mov ebp, esp
mov edx, [ebp+8]                    ; edx points to the argument string

.debug:
    mov bl, byte [edx]                      ; load first byte of debugStr (bl_1 = '-', bl_2 = 'd')
    cmp bl, '-'                        ; cmp char by char
    jnz .stack
    inc edx                            ; get ready for next char
    mov bl, byte [edx]                      ; load second byte of debugStr (bl_1 = '-', bl_2 = 'd')
    cmp bl, 'd'                        ; cmp char by char
    jnz .stack
    mov [debug_mode], dword 1
    jmp end

    .stack:
    mov edx, [ebp+8]                ; ecx points to the argument string
    xor ebx, ebx
    xor eax, eax
    mov ecx, 2
.loop: 
    mov bl, [edx]                   ; get byte pointed to by edx
    cmp bl, '9'                     ; if larger than 9 => digit is a letter (assuming valid input)
    ja .letter                      ; jmp to proceesing a letter digit
    sub bl, '0'
    ja .mul                         
.letter:
    sub bl, 37h
.mul:
    mov edi, 16
    mul edi
    add eax, ebx
    inc edx
    loop .loop

    mov edi, 4
    mul edi
; at this point eax should hold the INT value of stack_size
    mov [capacity], eax             

end:
    pop edx
    pop ecx
    pop ebx
    mov esp, ebp
    pop ebp
    ret

Any idea of what could be the reason? or clarifications about reading cmdline args? As well as the use of lea (load effective address) to this purpose and how it differs from a simple mov?

Thanks in advance.

giorgioh
  • 377
  • 1
  • 13
  • 2
    It's unclear why you are looping at `.nextArg` if you only want to process one argument. You are not advancing `eax` anyway. Also, `argv` is a `char**` so you need to dereference it. Split your problem into argument access and hex conversion. Verify each one separately. Learn to use a debugger. – Jester May 28 '20 at 11:51
  • @Jester I actually might have 2 arguments , a number and a debug mode – giorgioh May 28 '20 at 11:54
  • So increment EAX inside the loop in `main`. Do that *before* passing it so you loop starting with `argv[1]` because `argv[0]` is by convention the program name. With a debugger you can see what your current function is doing: passing `char *p = argv[0]`. Also, pick a call-preserved register like EDI that `process_arg` doesn't modify, not EAX. In the standard calling convention, EAX, ECX, and EDX are call-clobbered. (Others aren't so your function violates that for EBX) – Peter Cordes May 28 '20 at 19:36
  • 1
    In the first code excerpt, it loads [ebp+16] into eax. But argv is at [ebp+12]. To get argv[1], it can’t load [ebp+16], it has to load argv into a register and dereference it: `mov edi, [ebp+12]; mov eax, [edi+4]`. – prl May 29 '20 at 02:03

0 Answers0