The build task (or NASM) is annoying

I used to compile my asm code with TASM (on winXP), but I had some problems, so now I use NASM (on Linux). This snippet shows what I'm trying to do:

(gdb) list 35 30 xor ecx,ecx # ecx is a counter 31 mov bl, ' ' # this is what I'm looking for 32 count_spaces: 33 mov al,[esi] # grab a char 34 jz spaces_counted # is this the end? 35 inc esi # next char 36 cmp al,bl # found one? 37 jne count_spaces # nope, loop 38 inc ecx # yep, inc counter 39 jmp count_spaces # and loop 

This looks right to me, but:

 Breakpoint 1, main () at project1.asm:30 30 xor ecx,ecx (gdb) display (char) $al 1: (char) $al = 0 '\000' (gdb) display (char) $bl 2: (char) $bl = 0 '\000' (gdb) next 31 mov bl, ' ' 2: (char) $bl = 0 '\000' 1: (char) $al = 0 '\000' (gdb) count_spaces () at project1.asm:33 33 mov al,[esi] 2: (char) $bl = 0 '\000' 1: (char) $al = 0 '\000' (gdb) 

I do not understand why al and bl not changed.
I'm sure my code is correct, but .. I think I missed some version of NASM? BTW compiled with

 nasm -f elf -l project1.lst -o project1.o -i../include/ -g project1.asm 

After compilation, I parsed the output and got:

  80483ec: 31 c9 xor %ecx,%ecx 80483ee: bb 20 00 00 00 mov $0x20,%ebx 080483f3 <count_spaces>: 80483f3: 8b 06 mov (%esi),%eax 80483f5: 3d 00 00 00 00 cmp $0x0,%eax 80483fa: 74 0b je 8048407 <spaces_counted> 80483fc: 46 inc %esi 80483fd: 39 d8 cmp %ebx,%eax 80483ff: 75 f2 jne 80483f3 <count_spaces> 8048401: 41 inc %ecx 8048402: e9 ec ff ff ff jmp 80483f3 <count_spaces> 
+4
source share
4 answers

Note that GDB does not know about 8 or 16-bit aliases. It will always print 0 for al, bl, ax, bx , etc. You should use eax, ebx , etc .:

 (gdb) info registers bl Invalid register `bl' (gdb) info registers bx Invalid register `bx' (gdb) info registers ebx ebx 0xf7730ff4 -143454220 (gdb) p $bl $1 = void (gdb) p $bx $2 = void (gdb) p $ebx $3 = -143454220 (gdb) p/x $bl $4 = Value can't be converted to integer. (gdb) p/x $bx $5 = Value can't be converted to integer. (gdb) p/x $ebx $6 = 0xf7730ff4 (gdb) p (char) $bl $7 = 0 '\0' (gdb) p (char) $bx $8 = 0 '\0' (gdb) p (char) $ebx $9 = -12 'Γ΄' 
+6
source

The Jester has the correct answer , and he deserves a vote.

But I would like to add something too long for a comment: you can teach gdb display sub-registers, if you want, using hook-stop >, which starts just before any display happens, by adding the following to your .gdbinit file:

 define hook-stop set $bl=($ebx & 0xff) set $bh=(($ebx & 0xff00) >> 8) set $bx=($ebx & 0xffff) end 

(obviously for other registers). display $bl etc. will work as you expect.

+6
source

I'm not sure if this is the problem you noticed, but I see one pretty obvious problem in your code. On x86, a mov does not affect flags. Your code:

 33 mov al,[esi] # grab a char 34 jz spaces_counted # is this the end? 

It is assumed that when loading al from [esi] , the z flag will be updated to reflect the contents of al. This is not true. To check if the value you just downloaded is zero, you need to add an explicit test:

 mov al, [esi] test al, al jz spaces_counted 

The value in the register should be changed earlier, but the flags should not be updated to reflect the value.

As for whether nasm gave the correct instructions, I would parse the code to see what actually exists. It’s hard right now to guess if the problem lies with nasm or with gdb. Of course, disassemblers also cannot be without errors, but I would be a little surprised to see that the problem with the code is simple.

+1
source

Flags do not change mov, so jz on line 34 does not make sense. If you follow the code from the initial xor , this is the only command that changes the flags, so when the code reaches jz on line 34, it just jumps (because xor left it to zero). This does not explain the immutable values ​​of al or bl, but there may have been some optimization that takes into account that jz always runs due to xor.

0
source

Source: https://habr.com/ru/post/1342536/


All Articles