# Assembly level debugging problem

## Homework Statement

(This is x86 Assembly Language.)
You are charged with maintaining a large C program, and you come across the following code:

Code:
typedef struct{
int left;
a_struct a[CNT];
int right;
}  b_struct;

void test(int i, b_struct *bp)
{
int n = bp->left + bp->right;
a_struct *ap = &bp->a[i];
ap->x[ap->idx] = n;
}

Disassembled code:
Code:
00000000 <test>:
0: 55                            push %ebp
1: 89 e5                         mov  %esp,%ebp
3: 8b 45 08                      mov  0x8(%ebp),%eax
6: 8b 4d 0c                      mov  0xc(%ebp),%ecx
9: 8d 04 80                      lea  (%eax,%eax,4),%eax
c: 03 44 81 04                   add  0x4(%ecx,%eax,4),%eax
10: 8b 91 b8 00 00 00            mov  0xb8(%ecx),%edx
16: 03 11                        add  (%ecx),%edx
18: 89 54 81 08                  mov  %edx,0x8(%ecx,%eax,4)
1c: 5d                           pop  %ebp
1d: c3                           ret

The declarations of the compile-time constant CNT and teh structure a_struct are in a file for which you do not have the necessary access privilege. Fortunately, you have a copy of the '.o' version of code, which you are able to disassemble with the objdump program, yielding the disassembly shown. Using your reverse engineering skills, deduce the following:

A. The value of CNT
B. A complete declaration of structure a_struct. Assume that the only fields in this structure are idx and x.

## The Attempt at a Solution

Well I said that eax should be 8 above the value in ebp and ecx should be 12 above ebp. I said ebp was 0 so then in the "lea" command I said that eax was placed into address 40 (4 times eax, plus eax). After that I said eax was changed to 44 (the add command). ecx was added to 0xb8 and placed into edx and that value is 196. edx (196) was added to ecx (12) and called edx and that value is 208. That value is then loaded into address 52, therefore, I believe, CNT is equal to 52?

Assembly language really confuses me as my prof has been speeding through it at an incredibly fast pace. Any help, as in trying to guide me through it and, especially, pointing out my surely grievous errors would be absolutely wonderful.

Mark44
Mentor

## Homework Statement

(This is x86 Assembly Language.)
You are charged with maintaining a large C program, and you come across the following code:

Code:
typedef struct{
int left;
a_struct a[CNT];
int right;
}  b_struct;

void test(int i, b_struct *bp)
{
int n = bp->left + bp->right;
a_struct *ap = &bp->a[i];
ap->x[ap->idx] = n;
}

Disassembled code:
Code:
00000000 <test>:
0: 55                            push %ebp
1: 89 e5                         mov  %esp,%ebp
3: 8b 45 08                      mov  0x8(%ebp),%eax
6: 8b 4d 0c                      mov  0xc(%ebp),%ecx
9: 8d 04 80                      lea  (%eax,%eax,4),%eax
c: 03 44 81 04                   add  0x4(%ecx,%eax,4),%eax
10: 8b 91 b8 00 00 00            mov  0xb8(%ecx),%edx
16: 03 11                        add  (%ecx),%edx
18: 89 54 81 08                  mov  %edx,0x8(%ecx,%eax,4)
1c: 5d                           pop  %ebp
1d: c3                           ret

The declarations of the compile-time constant CNT and teh structure a_struct are in a file for which you do not have the necessary access privilege. Fortunately, you have a copy of the '.o' version of code, which you are able to disassemble with the objdump program, yielding the disassembly shown. Using your reverse engineering skills, deduce the following:

A. The value of CNT
B. A complete declaration of structure a_struct. Assume that the only fields in this structure are idx and x.

## The Attempt at a Solution

Well I said that eax should be 8 above the value in ebp and ecx should be 12 above ebp.
I'm a little rusty at this, since the x86 assembly work I did was about 18 years ago, and some of the instructions look a little different.

The instructions push %ebp, mov %esp,%ebp at the beginning and the pop %ebp instruction near the end are the prolog and epilog, respectively, that the compiler generates to keep track of the stack frame for the test function. The first of these three instructions saves the current stack-frame pointer (base pointer), and then copies the base pointer to the stack pointer. Just before the ret instruction, pop %ebp pops the value off the stack into the base pointer, getting it back to what it was before the function started.

The next two instructions, mov 0x8(%ebp),%eax and mov 0xc(%ebp),%ecx, are copying the parameters of test in right-to-left order. eax holds the address specified in bp (the struct pointer), and it is copied to the location pointed to by ebp + 8. ecx holds the value for i, and it is copied to ebp + 12.

I doubt that ebp is 0.
I said ebp was 0 so then in the "lea" command I said that eax was placed into address 40 (4 times eax, plus eax). After that I said eax was changed to 44 (the add command). ecx was added to 0xb8 and placed into edx and that value is 196. edx (196) was added to ecx (12) and called edx and that value is 208. That value is then loaded into address 52, therefore, I believe, CNT is equal to 52?

Assembly language really confuses me as my prof has been speeding through it at an incredibly fast pace. Any help, as in trying to guide me through it and, especially, pointing out my surely grievous errors would be absolutely wonderful.

I need to stop and eat dinner now, but I'll think about this some more. If I were you and I had access to a C compiler I would actually compile this code and look at it in the debugger, preferably one that disassembles the source code. Then I could see the values that are in the various registers and how the stack frame looks and so on.

How would I go about finding the value of ebp though (without using, say, info registers in gdb)? I guess that's where I'm stuck. I can figure out what the body of the function is doing, it just takes a bit of thought, but the beginning values are what confuses me.

With regard to this problem, would I be correct in assuming that CNT should equal the size of an array?

Mark44
Mentor
Just assume some value for ebp. What I meant was that it was very unlikely to be 0.

CNT is not the size of the array, but rather the number of elements are in it. Here I'm using size to mean the size in bytes.

There are a couple of lines of code that bother me
Code:
mov  0xb8(%ecx), %edx
add  (%ecx), %edx
In the first line, the value of edx is copied to the location pointed to by ecx + 0xb8. I think that's what that means. The assembly code here seems to by AT&T style rather than Intel style, which I'm more familiar with. What bothers me is what value is being copied? This line of code is the first one that has edx as an operand.

Same problem with the following line of code, which seems to be adding edx to the location pointed to by ecx.

I retract my earlier remarks about which parameters are which. Apparently the calling code is passing the arguments in registers, not on the stack. My guess now is that parameter i is passed in the eax register, and parameter bp is passed in the ecx register.

Hope that helps.

Ok, you can just assume a value for epb. That's what I thought, but I never read it anywhere so I wasn't sure.

In the first line, the value of edx is copied to the location pointed to by ecx + 0xb8. I think that's what that means. The assembly code here seems to by AT&T style rather than Intel style, which I'm more familiar with. What bothers me is what value is being copied? This line of code is the first one that has edx as an operand.

Well I know the way mov statements work is that it is structured Soruce,Destination so that means the value of 0xb8 + the value stored in the register at %ecx is stored into the register at %edx. At least I think that's what it's saying. I know for sure it goes Source,Destination though.

Thanks for all the help thus far, I'm going to run through it again after dinner and figure it out.

Mark44
Mentor
OK, I think I'm finally up to speed here. I didn't realize that AT&T syntax was completely backwards from Intel syntax. For example, in Intel syntax, it's mov dest, src, but in AT&T syntax, it's mov src, dest. That really threw me. I found a link to AT&T assembly syntax here.

I've added comments that indicate what I think is going on.

Code:
push %ebp                  ; push stack frame pointer (ebp) onto stack
mov  %esp,%ebp             ; copy stack pointer to ebp
mov  0x8(%ebp),%eax        ; copy value (i ?) at ebp + 8 to eax
mov  0xc(%ebp),%ecx        ; copy value (bp ?) at ebp + 12 to ecx
lea  (%eax,%eax,4),%eax    ; not sure here - I think this replaces value in eax with 5*eax
add  0x4(%ecx,%eax,4),%eax ; add value at ecx + 4*eax + 4 to eax
mov  0xb8(%ecx),%edx       ; copy value at ecx + 184 to edx
add  (%ecx),%edx           ; add value at ecx to edx
mov  %edx,0x8(%ecx,%eax,4) ; copy value in ecx to ecx + 4*eax + 8
pop  %ebp                  ; restore stack frame pointer to original value
ret                        ; return to caller

Ok, I agree with you on what is going on there. So, does that mean the following is correct?

1: Assume value for ebp. I say 0 just to make everything easier.
2: esp = ebp = 0
3: eax = 8
4: ecx = 12
5: address of eax is 40 (4*eax + eax)
6: eax = 56
7: edx = 196
8: edx = 208 (196 + ecx)
9: value of edx move to address 244 (4*eax + ecx)

And so eax = i in the program so CNT should be equal to 56, correct?