Related
C code
#include <stdio.h>
int fibonacci(int);
int main()
{
int x = fibonacci(3);
printf("Fibonacci is : %d",x);
return 0;
}
Assembly
section .text
global fibonacci
fibonacci:
push ebp;
mov ebp, esp;
; initialize
mov dword [prev], 0x00000000;
mov dword [cur], 0x00000001;
mov byte [it], 0x01;
mov eax, dword [ebp + 8]; // n = 3
mov byte [n], al;
getfib:
xor edx,edx;
mov dl, byte [n];
cmp byte [it] , dl;
jg loopend;
mov eax,dword [prev];
add eax, dword [cur];
mov ebx, dword [cur];
mov dword [prev], ebx;
mov dword [cur] , eax;
inc byte [it];
jmp getfib;
loopend:
mov eax, dword [cur];
pop ebp;
ret;
section .bss
it resb 1
prev resd 1
cur resd 1
n resb 1
I was trying to run this assembly function in C code and on debugging , i saw that value in variable x in C code is right but there is some error coming when i use the printf function
Need Help on it
Command to compile:
nasm -f elf32 asmcode.asm -o a.o
gcc -ggdb -no-pie -m32 a.o ccode.c -o a.out
Click Below Pictures if they seem blurred
Below is debug before printf execute
Below is after printf execute
Your code does not preserve the ebx register which is a callee-preserved register. The main function apparently tries to do some rip-relative addressing to obtain the address of the format string for printf using ebx as a base register. This fails because your code overwrote ebx.
To fix this issue, make sure to save all callee-saved registers before you use them and then restore their value on return. For example, you can do
fibonacci:
push ebp
mov ebp, esp
push ebx ; <---
...
pop ebx ; <---
pop ebp
ret
I want to have a register containing 4 bytes of address and 4 bytes of data. For that, I thought about building it in an array of structures (containing address and data as members) or in a matrix. Here a sample code to test what I want to achieve:
#include <stdio.h>
#include <stdint.h>
void reg_init();
#define REG_SIZE 1
typedef struct Reg{
uint8_t addr[4];
uint8_t data[4];
} reg;
static reg reg_struct[REG_SIZE];
static uint8_t reg_matrix[REG_SIZE][8];
int main()
{
int index=-1;
reg_init();
for(int i=0; i<REG_SIZE; i++)
{
uint8_t addr_to_check[4]={0x12,0x34,0x56,0x78};
// FOR STRUCT
for(int j=0; j<4; j++)
{
if(addr_to_check[j]!=reg_struct[i].addr[j]) break;
if(j==3) index = i;
}
//FOR MATRIX
for(int j=0; j<4; j++)
{
if(addr_to_check[j]!=reg_matrix[i][j]) break;
if(j==3) index = i;
}
}
if (index<0) printf("Address not found\n");
else printf("Address at index: %i",index);
return 0;
}
void reg_init()
{
// Register init for testing
reg_struct[0].addr[0] = 0x12;
reg_struct[0].addr[1] = 0x34;
reg_struct[0].addr[2] = 0x56;
reg_struct[0].addr[3] = 0x78;
reg_struct[0].data[0] = 0x01;
reg_struct[0].data[1] = 0x02;
reg_struct[0].data[2] = 0x03;
reg_struct[0].data[3] = 0x04;
reg_matrix[0][0] = 0x12;
reg_matrix[0][1] = 0x34;
reg_matrix[0][2] = 0x56;
reg_matrix[0][3] = 0x78;
reg_matrix[0][4] = 0x01;
reg_matrix[0][5] = 0x02;
reg_matrix[0][6] = 0x03;
reg_matrix[0][7] = 0x04;
}
The example shows just a unit size register, but the size will be much higher (up to 8 bytes). Overall, I'm interested in optimization in terms of performance. Does it really care to use one or another, or will the compiler build the same machine code?
Below is the assembly of the above code created using visual studio 2019.
Look at record line number ; Line 50 and ; Line 51 it looks like compiler has created same assembly code for both matrix and structure.
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.20.27508.1
TITLE D:\main.c
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC ___local_stdio_printf_options
PUBLIC __vfprintf_l
PUBLIC _printf
PUBLIC _reg_init
PUBLIC _main
EXTRN ___acrt_iob_func:PROC
EXTRN ___stdio_common_vfprintf:PROC
_DATA SEGMENT
COMM ?_OptionsStorage#?1??__local_stdio_printf_options##9#9:QWORD ; `__local_stdio_printf_options'::`2'::_OptionsStorage
_DATA ENDS
_BSS SEGMENT
_reg_struct DQ 01H DUP (?)
_reg_matrix DB 08H DUP (?)
_BSS ENDS
_DATA SEGMENT
$SG8132 DB 'Address not found', 0aH, 00H
ORG $+1
$SG8133 DB 'Address at index: %i', 00H
_DATA ENDS
; Function compile flags: /Odtp
_TEXT SEGMENT
_index$ = -20 ; size = 4
_addr_to_check$1 = -16 ; size = 4
_j$2 = -12 ; size = 4
_j$3 = -8 ; size = 4
_i$4 = -4 ; size = 4
_main PROC
; File D:\main.c
; Line 16
push ebp
mov ebp, esp
sub esp, 20 ; 00000014H
; Line 17
mov DWORD PTR _index$[ebp], -1
; Line 18
call _reg_init
; Line 19
mov DWORD PTR _i$4[ebp], 0
jmp SHORT $LN4#main
$LN2#main:
mov eax, DWORD PTR _i$4[ebp]
add eax, 1
mov DWORD PTR _i$4[ebp], eax
$LN4#main:
cmp DWORD PTR _i$4[ebp], 1
jge $LN3#main
; Line 21
mov BYTE PTR _addr_to_check$1[ebp], 18 ; 00000012H
mov BYTE PTR _addr_to_check$1[ebp+1], 52 ; 00000034H
mov BYTE PTR _addr_to_check$1[ebp+2], 86 ; 00000056H
mov BYTE PTR _addr_to_check$1[ebp+3], 120 ; 00000078H
; Line 23
mov DWORD PTR _j$3[ebp], 0
jmp SHORT $LN7#main
$LN5#main:
mov ecx, DWORD PTR _j$3[ebp]
add ecx, 1
mov DWORD PTR _j$3[ebp], ecx
$LN7#main:
cmp DWORD PTR _j$3[ebp], 4
jge SHORT $LN6#main
; Line 25
mov edx, DWORD PTR _j$3[ebp]
movzx eax, BYTE PTR _addr_to_check$1[ebp+edx]
mov ecx, DWORD PTR _j$3[ebp]
mov edx, DWORD PTR _i$4[ebp]
movzx ecx, BYTE PTR _reg_struct[ecx+edx*8]
cmp eax, ecx
je SHORT $LN11#main
jmp SHORT $LN6#main
$LN11#main:
; Line 26
cmp DWORD PTR _j$3[ebp], 3
jne SHORT $LN12#main
mov edx, DWORD PTR _i$4[ebp]
mov DWORD PTR _index$[ebp], edx
$LN12#main:
; Line 27
jmp SHORT $LN5#main
$LN6#main:
; Line 30
mov DWORD PTR _j$2[ebp], 0
jmp SHORT $LN10#main
$LN8#main:
mov eax, DWORD PTR _j$2[ebp]
add eax, 1
mov DWORD PTR _j$2[ebp], eax
$LN10#main:
cmp DWORD PTR _j$2[ebp], 4
jge SHORT $LN9#main
; Line 32
mov ecx, DWORD PTR _j$2[ebp]
movzx edx, BYTE PTR _addr_to_check$1[ebp+ecx]
mov eax, DWORD PTR _j$2[ebp]
mov ecx, DWORD PTR _i$4[ebp]
movzx eax, BYTE PTR _reg_matrix[eax+ecx*8]
cmp edx, eax
je SHORT $LN13#main
jmp SHORT $LN9#main
$LN13#main:
; Line 33
cmp DWORD PTR _j$2[ebp], 3
jne SHORT $LN14#main
mov ecx, DWORD PTR _i$4[ebp]
mov DWORD PTR _index$[ebp], ecx
$LN14#main:
; Line 34
jmp SHORT $LN8#main
$LN9#main:
; Line 35
jmp $LN2#main
$LN3#main:
; Line 36
cmp DWORD PTR _index$[ebp], 0
jge SHORT $LN15#main
push OFFSET $SG8132
call _printf
add esp, 4
jmp SHORT $LN16#main
$LN15#main:
; Line 37
mov edx, DWORD PTR _index$[ebp]
push edx
push OFFSET $SG8133
call _printf
add esp, 8
$LN16#main:
; Line 38
xor eax, eax
; Line 39
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
; Function compile flags: /Odtp
_TEXT SEGMENT
_reg_init PROC
; File D:\main.c
; Line 41
push ebp
mov ebp, esp
; Line 43
mov eax, 8
imul ecx, eax, 0
mov edx, 1
imul eax, edx, 0
mov BYTE PTR _reg_struct[ecx+eax], 18 ; 00000012H
; Line 44
mov ecx, 8
imul edx, ecx, 0
mov eax, 1
shl eax, 0
mov BYTE PTR _reg_struct[edx+eax], 52 ; 00000034H
; Line 45
mov ecx, 8
imul edx, ecx, 0
mov eax, 1
shl eax, 1
mov BYTE PTR _reg_struct[edx+eax], 86 ; 00000056H
; Line 46
mov ecx, 8
imul edx, ecx, 0
mov eax, 1
imul ecx, eax, 3
mov BYTE PTR _reg_struct[edx+ecx], 120 ; 00000078H
; Line 47
mov edx, 8
imul eax, edx, 0
mov ecx, 1
imul edx, ecx, 0
mov BYTE PTR _reg_struct[eax+edx+4], 1
; Line 48
mov eax, 8
imul ecx, eax, 0
mov edx, 1
shl edx, 0
mov BYTE PTR _reg_struct[ecx+edx+4], 2
; Line 49
mov eax, 8
imul ecx, eax, 0
mov edx, 1
shl edx, 1
mov BYTE PTR _reg_struct[ecx+edx+4], 3
; Line 50
mov eax, 8
imul ecx, eax, 0
mov edx, 1
imul eax, edx, 3
mov BYTE PTR _reg_struct[ecx+eax+4], 4
; Line 51
mov ecx, 8
imul edx, ecx, 0
mov eax, 1
imul ecx, eax, 0
mov BYTE PTR _reg_matrix[edx+ecx], 18 ; 00000012H
; Line 52
mov edx, 8
imul eax, edx, 0
mov ecx, 1
shl ecx, 0
mov BYTE PTR _reg_matrix[eax+ecx], 52 ; 00000034H
; Line 53
mov edx, 8
imul eax, edx, 0
mov ecx, 1
shl ecx, 1
mov BYTE PTR _reg_matrix[eax+ecx], 86 ; 00000056H
; Line 54
mov edx, 8
imul eax, edx, 0
mov ecx, 1
imul edx, ecx, 3
mov BYTE PTR _reg_matrix[eax+edx], 120 ; 00000078H
; Line 55
mov eax, 8
imul ecx, eax, 0
mov edx, 1
shl edx, 2
mov BYTE PTR _reg_matrix[ecx+edx], 1
; Line 56
mov eax, 8
imul ecx, eax, 0
mov edx, 1
imul eax, edx, 5
mov BYTE PTR _reg_matrix[ecx+eax], 2
; Line 57
mov ecx, 8
imul edx, ecx, 0
mov eax, 1
imul ecx, eax, 6
mov BYTE PTR _reg_matrix[edx+ecx], 3
; Line 58
mov edx, 8
imul eax, edx, 0
mov ecx, 1
imul edx, ecx, 7
mov BYTE PTR _reg_matrix[eax+edx], 4
; Line 59
pop ebp
ret 0
_reg_init ENDP
_TEXT ENDS
; Function compile flags: /Odtp
; COMDAT _printf
_TEXT SEGMENT
__Result$ = -8 ; size = 4
__ArgList$ = -4 ; size = 4
__Format$ = 8 ; size = 4
_printf PROC ; COMDAT
; File C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt\stdio.h
; Line 954
push ebp
mov ebp, esp
sub esp, 8
; Line 957
lea eax, DWORD PTR __Format$[ebp+4]
mov DWORD PTR __ArgList$[ebp], eax
; Line 958
mov ecx, DWORD PTR __ArgList$[ebp]
push ecx
push 0
mov edx, DWORD PTR __Format$[ebp]
push edx
push 1
call ___acrt_iob_func
add esp, 4
push eax
call __vfprintf_l
add esp, 16 ; 00000010H
mov DWORD PTR __Result$[ebp], eax
; Line 959
mov DWORD PTR __ArgList$[ebp], 0
; Line 960
mov eax, DWORD PTR __Result$[ebp]
; Line 961
mov esp, ebp
pop ebp
ret 0
_printf ENDP
_TEXT ENDS
; Function compile flags: /Odtp
; COMDAT __vfprintf_l
_TEXT SEGMENT
__Stream$ = 8 ; size = 4
__Format$ = 12 ; size = 4
__Locale$ = 16 ; size = 4
__ArgList$ = 20 ; size = 4
__vfprintf_l PROC ; COMDAT
; File C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt\stdio.h
; Line 642
push ebp
mov ebp, esp
; Line 643
mov eax, DWORD PTR __ArgList$[ebp]
push eax
mov ecx, DWORD PTR __Locale$[ebp]
push ecx
mov edx, DWORD PTR __Format$[ebp]
push edx
mov eax, DWORD PTR __Stream$[ebp]
push eax
call ___local_stdio_printf_options
mov ecx, DWORD PTR [eax+4]
push ecx
mov edx, DWORD PTR [eax]
push edx
call ___stdio_common_vfprintf
add esp, 24 ; 00000018H
; Line 644
pop ebp
ret 0
__vfprintf_l ENDP
_TEXT ENDS
; Function compile flags: /Odtp
; COMDAT ___local_stdio_printf_options
_TEXT SEGMENT
___local_stdio_printf_options PROC ; COMDAT
; File C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt\corecrt_stdio_config.h
; Line 86
push ebp
mov ebp, esp
; Line 88
mov eax, OFFSET ?_OptionsStorage#?1??__local_stdio_printf_options##9#9 ; `__local_stdio_printf_options'::`2'::_OptionsStorage
; Line 89
pop ebp
ret 0
___local_stdio_printf_options ENDP
_TEXT ENDS
END
I wrote this classic function : (in 32-bit mode)
void ex(size_t a, size_t b)
{
size_t c;
c = a;
a = b;
b = c;
}
I call it inside the main as follows :
size_t a = 4;
size_t b = 5;
ex(a,b);
What I was expecting from the assembly code generated when entering the function is something like this :
1-Push the values of b and a in the stack : (which was done)
mov eax,dword ptr [b]
push eax
mov ecx,dword ptr [a]
push ecx
2-Use the values of a and b in the stack :
push ebp
mov ebp, esp
sub esp, 4
c = a;
mov eax, dword ptr [ebp+8]
mov dword ptr [ebp-4], eax
and so on for the other variables.
However, this is what I find when debugging :
push ebp
mov ebp,esp
sub esp,0CCh // normal since it's in debug with ZI option
push ebx
push esi
push edi
lea edi,[ebp-0CCh]
mov ecx,33h
mov eax,0CCCCCCCCh
rep stos dword ptr es:[edi]
size_t c;
c = a;
mov eax,dword ptr [a]
mov dword ptr [c],eax
Why is it using the variable a directly instead of calling the value stored in the stack? I don't understand...
The debugger doesn't show the instruction using ebp to access a. The same syntax is permitted when you write inline assembly. Otherwise the reason that dword ptr still appears.
It is easy to get it your preferred way, right click > untick "Show Symbol Names".
Using the assembly output option (right click on file name, properties, ...), I get what you expect from debug assembly output. This could depend on which version of VS you use. For this example, I used VS2005. I have VS2015 on a different system, but didn't try it yet.
_c$ = -8 ; size = 4
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_ex PROC ; COMDAT
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd ;fill with 0cccccccch
mov eax, DWORD PTR _a$[ebp]
mov DWORD PTR _c$[ebp], eax
mov eax, DWORD PTR _b$[ebp]
mov DWORD PTR _a$[ebp], eax
mov eax, DWORD PTR _c$[ebp]
mov DWORD PTR _b$[ebp], eax
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_ex ENDP
Note this doesn't work, you need to use pointers for the swap to work.
void ex(size_t *pa, size_t *pb)
{
size_t c;
c = *pa;
*pa = *pb;
*pb = c;
}
which gets translated into:
_c$ = -8 ; size = 4
_pa$ = 8 ; size = 4
_pb$ = 12 ; size = 4
_ex PROC ; COMDAT
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
mov eax, DWORD PTR _pa$[ebp]
mov ecx, DWORD PTR [eax]
mov DWORD PTR _c$[ebp], ecx
mov eax, DWORD PTR _pa$[ebp]
mov ecx, DWORD PTR _pb$[ebp]
mov edx, DWORD PTR [ecx]
mov DWORD PTR [eax], edx
mov eax, DWORD PTR _pb$[ebp]
mov ecx, DWORD PTR _c$[ebp]
mov DWORD PTR [eax], ecx
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_ex ENDP
When compiling a C program to an object file, it's easy to get the Microsoft compiler to give you an annotated disassembly (with names of functions and variables, source line numbers etc.) using cl /Fa.
I'm trying to get something similar from the final linked executable (assuming the program was compiled with appropriate debug information), which seems to be trickier; dumpbin and objdump seem to only provide non-annotated disassembly.
What's the best way to obtain this?
if you have the program compiled with debuginfo windbg should provide disassembly of a function with line numbers
sample code compiled with debug info and an assembly file generated with /Fa
C:\codesnips\comparesrc\debug>cl /Zi /Fa comparesrc.cpp /link /Debug
comparesrc.cpp
/out:comparesrc.exe
/debug
/Debug
comparesrc.obj
the source for the above compilation
C:\codesnips\comparesrc\debug>type comparesrc.cpp
#include <stdio.h> // standard include file
int main (void)
{ // this line will become prolog
printf("hello my dear source compare\n"); // see str in .data section
puts("c"); // will put a char* with line break to console
puts("om");
puts("pare");
int a,b,c,d;
a = 2; b =3 ; c = 4;
d = a+b-c; // 2+3 -4 = 1
printf("%d\n",d); // should print 1
d = (a*b)/c; // 2*3 /4 = 6 /4 numerator = 1
printf("%d\n",d); // should printf 1
d = (a*b)%c; // 2 * 3 % 4 denominator = 2
printf("%d\n",d); // should print 2
return 0; // lets generate a cod file and see the assembly
} // this line will get converted to epilog
the assembly file created by /Fa switch
C:\codesnips\comparesrc\debug>type comparesrc.asm
; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01
TITLE C:\codesnips\comparesrc\debug\comparesrc.cpp
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
CONST SEGMENT
$SG3850 DB 'hello my dear source compare', 0aH, 00H
ORG $+2
$SG3851 DB 'c', 00H
ORG $+2
$SG3852 DB 'om', 00H
ORG $+1
$SG3853 DB 'pare', 00H
ORG $+3
$SG3858 DB '%d', 0aH, 00H
$SG3859 DB '%d', 0aH, 00H
$SG3860 DB '%d', 0aH, 00H
CONST ENDS
PUBLIC _main
EXTRN _puts:PROC
EXTRN _printf:PROC
; Function compile flags: /Odtp
_TEXT SEGMENT
_c$ = -16 ; size = 4
_d$ = -12 ; size = 4
_b$ = -8 ; size = 4
_a$ = -4 ; size = 4
_main PROC
; File c:\codesnips\comparesrc\debug\comparesrc.cpp
; Line 3
push ebp
mov ebp, esp
sub esp, 16 ; 00000010H
; Line 4
push OFFSET $SG3850
call _printf
add esp, 4
; Line 5
push OFFSET $SG3851
call _puts
add esp, 4
; Line 6
push OFFSET $SG3852
call _puts
add esp, 4
; Line 7
push OFFSET $SG3853
call _puts
add esp, 4
; Line 9
mov DWORD PTR _a$[ebp], 2
mov DWORD PTR _b$[ebp], 3
mov DWORD PTR _c$[ebp], 4
; Line 10
mov eax, DWORD PTR _a$[ebp]
add eax, DWORD PTR _b$[ebp]
sub eax, DWORD PTR _c$[ebp]
mov DWORD PTR _d$[ebp], eax
; Line 11
mov ecx, DWORD PTR _d$[ebp]
push ecx
push OFFSET $SG3858
call _printf
add esp, 8
; Line 12
mov eax, DWORD PTR _a$[ebp]
imul eax, DWORD PTR _b$[ebp]
cdq
idiv DWORD PTR _c$[ebp]
mov DWORD PTR _d$[ebp], eax
; Line 13
mov edx, DWORD PTR _d$[ebp]
push edx
push OFFSET $SG3859
call _printf
add esp, 8
; Line 14
mov eax, DWORD PTR _a$[ebp]
imul eax, DWORD PTR _b$[ebp]
cdq
idiv DWORD PTR _c$[ebp]
mov DWORD PTR _d$[ebp], edx
; Line 15
mov eax, DWORD PTR _d$[ebp]
push eax
push OFFSET $SG3860
call _printf
add esp, 8
; Line 16
xor eax, eax
; Line 17
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
and finally disassembly of the complete main function using cdb (console version of windbg)
cdb -c ".lines;g main;uf #eip;q;" comparesrc.exe
Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
CommandLine: comparesrc.exe
0:000> cdb: Reading initial command '.lines;g main;uf #eip;q;'
Line number information will be loaded
comparesrc!main [c:\codesnips\comparesrc\debug\comparesrc.cpp # 3]:
3 00401010 55 push ebp
3 00401011 8bec mov ebp,esp
3 00401013 83ec10 sub esp,10h
4 00401016 685c8c4100 push offset comparesrc!__xt_z+0x120 (00418c5c)
4 0040101b e81b020000 call comparesrc!printf (0040123b)
4 00401020 83c404 add esp,4
5 00401023 687c8c4100 push offset comparesrc!__xt_z+0x140 (00418c7c)
5 00401028 e8bf000000 call comparesrc!puts (004010ec)
5 0040102d 83c404 add esp,4
6 00401030 68808c4100 push offset comparesrc!__xt_z+0x144 (00418c80)
6 00401035 e8b2000000 call comparesrc!puts (004010ec)
6 0040103a 83c404 add esp,4
7 0040103d 68848c4100 push offset comparesrc!__xt_z+0x148 (00418c84)
7 00401042 e8a5000000 call comparesrc!puts (004010ec)
7 00401047 83c404 add esp,4
9 0040104a c745fc02000000 mov dword ptr [ebp-4],2
9 00401051 c745f803000000 mov dword ptr [ebp-8],3
9 00401058 c745f004000000 mov dword ptr [ebp-10h],4
10 0040105f 8b45fc mov eax,dword ptr [ebp-4]
10 00401062 0345f8 add eax,dword ptr [ebp-8]
10 00401065 2b45f0 sub eax,dword ptr [ebp-10h]
10 00401068 8945f4 mov dword ptr [ebp-0Ch],eax
11 0040106b 8b4df4 mov ecx,dword ptr [ebp-0Ch]
11 0040106e 51 push ecx
11 0040106f 688c8c4100 push offset comparesrc!__xt_z+0x150 (00418c8c)
11 00401074 e8c2010000 call comparesrc!printf (0040123b)
11 00401079 83c408 add esp,8
12 0040107c 8b45fc mov eax,dword ptr [ebp-4]
12 0040107f 0faf45f8 imul eax,dword ptr [ebp-8]
12 00401083 99 cdq
12 00401084 f77df0 idiv eax,dword ptr [ebp-10h]
12 00401087 8945f4 mov dword ptr [ebp-0Ch],eax
13 0040108a 8b55f4 mov edx,dword ptr [ebp-0Ch]
13 0040108d 52 push edx
13 0040108e 68908c4100 push offset comparesrc!__xt_z+0x154 (00418c90)
13 00401093 e8a3010000 call comparesrc!printf (0040123b)
13 00401098 83c408 add esp,8
14 0040109b 8b45fc mov eax,dword ptr [ebp-4]
14 0040109e 0faf45f8 imul eax,dword ptr [ebp-8]
14 004010a2 99 cdq
14 004010a3 f77df0 idiv eax,dword ptr [ebp-10h]
14 004010a6 8955f4 mov dword ptr [ebp-0Ch],edx
15 004010a9 8b45f4 mov eax,dword ptr [ebp-0Ch]
15 004010ac 50 push eax
15 004010ad 68948c4100 push offset comparesrc!__xt_z+0x158 (00418c94)
15 004010b2 e884010000 call comparesrc!printf (0040123b)
15 004010b7 83c408 add esp,8
16 004010ba 33c0 xor eax,eax
17 004010bc 8be5 mov esp,ebp
17 004010be 5d pop ebp
17 004010bf c3 ret
You can use
Windbg -z <any image>
to perform disassembly or any inspection of that image (works with cdb \ kd as well).
You can see source lines, symbols, types - without having to actually run the program.
This is useful for looking at DLLs, but really necessary when you want to look at code compiled for another architecture or a device driver where you can't run in on your machine.
For example
cdb -z ntoskrnl.exe
will let you inspect the code of the windows kernel.
This is more powerful than a crashdump because you don't just see the code that is paged in - you can see all the code that is in the .exe
I have written a simple c code in visual studio. Here is the code ..
#include<stdio.h>
int global;
int onemore=5;
int main(){
int local;
static int slocal;
return 0;
}
and here is it's assembly after compiling in visual studio ..
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.21022.08
TITLE c:\Users\amit_bhaira\Documents\Visual Studio 2008\Projects\AssOneQuestion1\AssOneQuestion1\question1.c
.686P
->.XMM
->include listing.inc
->.model flat
->INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES
PUBLIC _onemore
_DATA SEGMENT
COMM _global:DWORD
_onemore DD 05H
_DATA ENDS
PUBLIC _main
->EXTRN__RTC_Shutdown:PROC
->EXTRN__RTC_InitBase:PROC
; COMDAT rtc$TMZ
; File c:\users\amit_bhaira\documents\visual studio 2008\projects\assonequestion1\assonequestion1\question1.c
rtc$TMZ SEGMENT
->__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ ENDS
; COMDAT rtc$IMZ
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ ENDS
; COMDAT _main
_TEXT SEGMENT
_main PROC ; COMDAT
; 4 : int main(){
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
->push ebx
->push esi
->push edi //why these(ebx,esi and edi) registers are pushed into the stack ??
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
; 5 : int local;
; 6 : ->static int slocal;
; 7 : return 0;
xor eax, eax
; 8 : }
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
I have put an arrow(->) in front of the lines that I didn't get. So please explain them.
Though I have taken a static variable inside the main method but no special steps are taken by the
compiler, what is that suppose to mean. Static varialbe is also going to be handled like other local
variable, no special storage for static variable. If Yes then how is the memory of static variable is preserved for the next function call ??