math.haifa.ac.ilmath.haifa.ac.il/.../lectures/lecture09/carch18.docx · web viewתוכניות...

Post on 28-Apr-2019

214 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

MinGcc תחת x86_64 תוכניות באסמבלי

. minGW64לצורך הקורס הזה הכי נוח בקומפילר

/https://sourceforge.net/projects/mingw-w64 ניתן להוריד אותו כאן:

.i686 ולא את ברירת המחדל x86_64גרסת ה-חשוב להתקין את

run terminalאחרי ההתקנה, בכל פעם שרוצים לעבוד צריך לעשות mingw-w64.bat ולהריץ את הקובץ cmdחלון מתוך התוכנה או לפתוח

.cmdמתוך חלון

, לתרגם את הקודCהכי מעשי לכתוב קוד של הפעולה הרצויה ב- לאסמבלי )ראה מיד( לקרואCלאסמבלי ע"י פקודת תרגום של תוכנית

את הפתרון משם וליעל את הקוד.

קצת שונה מזה שלgccהסינטקס ברירת מחדל של האסמבלי של ה- אינטל, בכדי לעבוד בסינטקס שאנחנו מכירים, בכדי להמיר לאסמבלי

נשתמש בפקודה

gcc –S –masm=intel myprog.c

ולשנות אותו לפי הצרכים.myprog.sולקבל קובץ

לאחר מכן לכתוב )במידת הצורך( קובץ תוכנית ראשית באסמבלי

( ולבסוף לקמפלmain.c)נניח

gcc main.c myprog.s

".a.exeקובץ ההרצה יהיה "

התייחסות לאוגרים:

4 הבתים הראשונים, 2לכל האוגרים ניתן להתיחס לבית התחתון, :r8הבתים הראשונים וכולו, למשל עבור

r8b, r8w, r8d, r8

,raxלשמונת האוגרים הראשונים אפשר להתיחס בשמות הישנים למשל eax, ax,ah,al-וכו', אבל ל rax אפשר גם לקרוא r0, r0d, r0l,r0b.'וכו

משתנים שלמים:

קומפילר הזה גודל המשתנים השלמים הם:ב

char 1 בית

short int 2 בתים

int 4 בתים

long int 4 בתים

long long int 8 בתים -

ניתן לראות זאת בתוכנית הזו:

// ints.c#include <stdio.h>

char c1=1,c2 = 1;short int si1=2, si2=2;int i1=3, i2=3;long int li1 = 4, li2= 4;long long int lli1=5, lli2 =5;

int main(){

printf("sizeof(char) = %d, sizeof(short int) = %d,\n" "sizeof(int) = %d, sizeof(long int) = %d,\n" "sizeof(long long int) = %d\n", sizeof(char), sizeof(short int), sizeof(int), sizeof(long int), sizeof(long long int));

c1 = c1 + c2;si1 = si1 + si2;i1 = i1 + i2;li1 = li1 + li2;lli1 = lli1 + lli2;

printf("c1 = %d, si1 = %d, i1 = %d, li1 = %ld, lli1 = %lld\n", c1, si1, i1, li1, lli1);

} //main

קומפילציה והרצה:

D:\asm64>gcc ints.c

D:\asm64>a.exesizeof(char) = 1, sizeof(short int) = 2,sizeof(int) = 4, sizeof(long int) = 4,sizeof(long long int) = 8c1 = 2, si1 = 4, i1 = 6, li1 = 8, lli1 = 10

D:\asm64>

עם התוכן הבא:ints.s נקבל קובץ gcc -S -masm=intel ints.cאחרי ביצוע

.file "ints.c"

.intel_syntax noprefix

.globl c1

.datac1:

.byte 1

.globl c2c2:

.byte 1

.globl si1

.align 2si1:

.word 2

.globl si2

.align 2si2:

.word 2

.globl i1

.align 4i1:

.long 3

.globl i2

.align 4i2:

.long 3

.globl li1

.align 4li1:

.long 4

.globl li2

.align 4li2:

.long 4

.globl lli1

.align 8lli1:

.quad 5

.globl lli2

.align 8lli2:

.quad 5

.def __main; .scl 2; .type 32; .endef

.section .rdata,"dr"

.align 8.LC0:

.ascii "sizeof(char) = %d, sizeof(short int) = %d,\12sizeof(int) = %d, sizeof(long int) = %d,\12sizeof(long long int) = %d\12\0"

.align 8.LC1:

.ascii "c1 = %d, si1 = %d, i1 = %d, li1 = %ld, lli1 = %lld\12\0"

.text

.globl main

.def main; .scl 2; .type 32; .endef

.seh_proc mainmain:

push rbp.seh_pushreg rbpmov rbp, rsp.seh_setframe rbp, 0sub rsp, 48.seh_stackalloc 48.seh_endprologuecall __mainmov QWORD PTR 40[rsp], 8mov QWORD PTR 32[rsp], 4mov r9d, 4mov r8d, 2mov edx, 1lea rcx, .LC0[rip]call printfmovzxeax, BYTE PTR c1[rip]mov edx, eaxmovzxeax, BYTE PTR c2[rip]add eax, edxmov BYTE PTR c1[rip], almovzxeax, WORD PTR si1[rip]mov edx, eaxmovzxeax, WORD PTR si2[rip]add eax, edxmov WORD PTR si1[rip], ax

mov edx, DWORD PTR i1[rip]mov eax, DWORD PTR i2[rip]add eax, edxmov DWORD PTR i1[rip], eaxmov edx, DWORD PTR li1[rip]mov eax, DWORD PTR li2[rip]add eax, edxmov DWORD PTR li1[rip], eaxmov rdx, QWORD PTR lli1[rip]mov rax, QWORD PTR lli2[rip]add rax, rdxmov QWORD PTR lli1[rip], raxmov rcx, QWORD PTR lli1[rip]mov edx, DWORD PTR li1[rip]mov r9d, DWORD PTR i1[rip]movzxeax, WORD PTR si1[rip]movsxr8d, axmovzxeax, BYTE PTR c1[rip]movsxeax, almov QWORD PTR 40[rsp], rcxmov DWORD PTR 32[rsp], edxmov edx, eaxlea rcx, .LC1[rip]call printfmov eax, 0add rsp, 48pop rbpret.seh_endproc.ident "GCC: (x86_64-posix-seh-rev1, Built by MinGW-W64 project) 6.3.0".def printf; .scl 2; .type 32; .endef

העברת פרמטרים

4למעט בקומפילר הזה הפרמטרים נדחפים למחסנית מימין לשמאל, שמוקצה להם מקום, אבל ערכיהם מועבריםהסקלרים הראשונים

או בחלקים שלהם, בהתאםrcx, rdx, r8, r9באוגרים )משמאל לימין( לגודל הפרמטר. לדוגמא, בקריאה

u = f(x, y, z);

, אםr8b הוא יועבר ב-char, הפרמטר השלישי משמאל הוא הוא zאם , ואם הואr8d יועבר ב-int, long, אם הוא r8w הוא יועבר ב-short intהוא

long long int-יועבר ב r8.

.cl, cx, ecx, rcx, הפרמטר הראשון יהיו xההעברות המקבילות ל-

לדוגמא, המימוש באסמבלי של התוכנית הבאה:

long long int z;

long long int fun(long long int x1,long long int x2,long long int x3,long long int x4,long long int x5,long long int x6,long long int x7,long long int x8,long long int x9,long long int x10){x1 = x1 + 1;x2 = x2 + 2;x3 = x3 + 3;x4 = x4 + 4;x5 = x5 + 5;x6 = x6 + 6;x7 = x7 + 7;x8 = x8 + 8;x9 = x9 + 9;x10 = x10 + 10;z = x1+x2+x3+x4+x5+x6+x7+x8+x9+x10;return z;}

יהיה:.file "pars1.c".intel_syntax noprefix

.comm z, 8, 3

.text

.globl fun

.def fun; .scl 2; .type 32; .endef

.seh_proc funfun:

push rbp.seh_pushreg rbpmov rbp, rsp.seh_setframe rbp, 0.seh_endprologuemov QWORD PTR 16[rbp], rcxmov QWORD PTR 24[rbp], rdxmov QWORD PTR 32[rbp], r8mov QWORD PTR 40[rbp], r9add QWORD PTR 16[rbp], 1add QWORD PTR 24[rbp], 2add QWORD PTR 32[rbp], 3add QWORD PTR 40[rbp], 4add QWORD PTR 48[rbp], 5add QWORD PTR 56[rbp], 6add QWORD PTR 64[rbp], 7add QWORD PTR 72[rbp], 8add QWORD PTR 80[rbp], 9add QWORD PTR 88[rbp], 10mov rdx, QWORD PTR 16[rbp]mov rax, QWORD PTR 24[rbp]add rdx, raxmov rax, QWORD PTR 32[rbp]add rdx, raxmov rax, QWORD PTR 40[rbp]add rdx, raxmov rax, QWORD PTR 48[rbp]

add rdx, raxmov rax, QWORD PTR 56[rbp]add rdx, raxmov rax, QWORD PTR 64[rbp]add rdx, raxmov rax, QWORD PTR 72[rbp]add rdx, raxmov rax, QWORD PTR 80[rbp]add rdx, raxmov rax, QWORD PTR 88[rbp]add rdx, raxlea rax, z[rip]mov QWORD PTR [rax], rdxlea rax, z[rip]mov rax, QWORD PTR [rax]pop rbpret.seh_endproc.ident "GCC: (x86_64-posix-seh-rev1, Built by MinGW-W64

project) 6.3.0"

דוגמאות:

// call_id3.c - call assembler subroutine idiv_mod64.s from C program #include <stdio.h> extern int idiv_mod64(long long int Num, long long int Denom, long long int *Q, long long int *Rem); int main() { long long int Num, Denom, Q, Rem; int No_Zero_Divide; printf("\nEnter Numerator, Denominator\n:");

scanf("%lld %lld",&Num, &Denom); No_Zero_Divide = idiv_mod64(Num,Denom,&Q,&Rem); if (No_Zero_Divide)

printf("\n %lld div %lld = %lld, mod(%lld,%lld) = %lld\n", Num, Denom, Q, Num, Denom, Rem);

else printf("\nError: Zero Divide.\n"); return 0; } /* main */

// idiv_mod64.cint idiv_mod64(long long int Num, long long int Denom, long long int *Q, long long int *Rem){ if(Denom == 0) return 0;*Q = Num/Denom;*Rem = Num % Denom;

return 1;

} // idiv_mod64קמפול ופלט ריצה:

D:\asm64>gcc call_id3.c idiv_mod64.c

D:\asm64>a.exe

Enter Numerator, Denominator:1000000000000 12345679

1000000000000 div 12345679 = 81000, mod(1000000000000,12345679) = 1000

D:\asm64> שנוצר ע"י idiv_mod64.sהקובץ

D:\asm64>gcc -S -masm=intel idiv_mod64.c

יהיה:.file "idiv_mod64.c".intel_syntax noprefix.text.globl idiv_mod64.def idiv_mod64; .scl 2; .type 32; .endef.seh_proc idiv_mod64

idiv_mod64:push rbp.seh_pushreg rbpmov rbp, rsp.seh_setframe rbp, 0.seh_endprologuemov QWORD PTR 16[rbp], rcxmov QWORD PTR 24[rbp], rdxmov QWORD PTR 32[rbp], r8mov QWORD PTR 40[rbp], r9cmp QWORD PTR 24[rbp], 0jne .L2mov eax, 0jmp .L3

.L2:mov rax, QWORD PTR 16[rbp]cqoidiv QWORD PTR 24[rbp]mov rdx, raxmov rax, QWORD PTR 32[rbp]mov QWORD PTR [rax], rdxmov rax, QWORD PTR 16[rbp]cqoidiv QWORD PTR 24[rbp]mov rax, QWORD PTR 40[rbp]mov QWORD PTR [rax], rdxmov eax, 1

.L3:pop rbpret

.seh_endproc

.ident "GCC: (x86_64-posix-seh-rev1, Built by MinGW-W64 project) 6.3.0"

ייעול ידני של התוכנית:.file "idiv_mod64.c".intel_syntax noprefix.text.globl idiv_mod64.def idiv_mod64; .scl 2; .type 32; .endef.seh_proc idiv_mod64

idiv_mod64:push rbp.seh_pushreg rbpmov rbp, rsp.seh_setframe rbp, 0.seh_endprologue

mov rbx,rdxcmp rbx, 0jne .L2mov eax, 0jmp .L3

.L2:mov rax,rcxcqoidiv rbxmov [r8], raxmov [r9], rdxmov eax, 1

.L3:pop rbpret.seh_endproc.ident "GCC: (x86_64-posix-seh-rev1, Built by MinGW-W64

project) 6.3.0".def print; .scl 2; .type 32; .endef

לעומת מימוש ידני באסמבלי:C הבודקת יעילות יחסית של המימוש ב-Cתוכנית

// call_id4.c - call assembler subroutine idiv_mod64.s from C program #include <stdio.h>#include <stdlib.h> extern int idiv_mod64(long long int Num, long long int Denom, long long int *Q, long long int *Rem); int main() { long long int Num, Denom, Q, Rem; int No_Zero_Divide; int i; printf("\nEnter Numerator, Denominator\n:"); scanf("%lld %lld",&Num, &Denom); system("time"); for(i=0; i< 1000000000;i++) No_Zero_Divide = idiv_mod64(Num,Denom,&Q,&Rem); system("time"); if (No_Zero_Divide)

printf("\n %lld div %lld = %lld, mod(%lld,%lld) = %lld\n", Num, Denom, Q, Num, Denom, Rem);

else printf("\nError: Zero Divide.\n"); return 0; } /* main */

:Cאפשר לראות את ההבדלים בייעול הודות לתכנות באסמבלי לעומת

F:\asm64>gcc call_id4.c idiv_mod64.c

F:\asm64>a.exe

Enter Numerator, Denominator:100000000000000 81The current time is: 1:46:47.23Enter the new time:The current time is: 1:47:07.96Enter the new time:

100000000000000 div 81 = 1234567901234, mod(100000000000000,81) = 46

F:\asm64>gcc call_id4.c idiv_mod64.s

F:\asm64>a.exe

Enter Numerator, Denominator:100000000000000 81The current time is: 1:47:55.35Enter the new time:The current time is: 1:48:05.91Enter the new time:

100000000000000 div 81 = 1234567901234, mod(100000000000000,81) = 46

F:\asm64>

.50% או 10/20שיפור של

קימפול התוכנית הבאה לאסמבלי ממחישה את שיטת מימוש:x86_64המשתנים ב-

unsigned long int g = 5555; // g - global variable

int f(int x) // x - parameter{ int y1; long int y2; // y1, y2 local //automatic int y3=99; // y3 local //automatic initialized static long int z=77; // z local static y1 = x+ z; z= x; y2 = y3; y3 = z; g = z+y2;} // f

:gcc –S –masm=intel vars1.c שנוצר מתוך vars1.sקובץ אסמבלי

.file "vars1.c"

.intel_syntax noprefix

.globl g

.data

.align 4g:

.long 5555

.text

.globl f

.def f; .scl 2; .type 32; .endef

.seh_proc ff:

push rbp.seh_pushreg rbpmov rbp, rsp.seh_setframe rbp, 0sub rsp, 16.seh_stackalloc 16.seh_endprologuemov DWORD PTR 16[rbp], ecxmov DWORD PTR -4[rbp], 99mov edx, DWORD PTR z.1775[rip]mov eax, DWORD PTR 16[rbp]add eax, edx

mov DWORD PTR -8[rbp], eaxmov eax, DWORD PTR 16[rbp]mov DWORD PTR z.1775[rip], eaxmov eax, DWORD PTR -4[rbp]mov DWORD PTR -12[rbp], eaxmov eax, DWORD PTR z.1775[rip]mov DWORD PTR -4[rbp], eaxmov edx, DWORD PTR z.1775[rip]mov eax, DWORD PTR -12[rbp]add eax, edxmov DWORD PTR g[rip], eaxnopadd rsp, 16pop rbpret.seh_endproc.data.align 4

z.1775:.long 77.ident "GCC: (x86_64-posix-seh-rev1, Built by MinGW-W64

project) 6.3.0"

rip שימו לב שגישה למשתנים סטטיים וגלובליים היא יחסית לאוגרהמשקפת את הכתובת הלינארית של הפקודה הנוכחית.

כפי שמשתמע מהתוכנית הבאה, ככל הנראה כאשר האסמבלרממש פקודה נוסח

mov rax,var1[rip]

הוו בונה היסט שככל הנראה מביאה בחשבון את המיקם של.var1הפקודה עצמה בנוסף למיקום של

מכיוון שאין סגמנתציה יותר, ומאחר ובכל זאת הכתובות הגלובליות לוקח על עצמו את ההצבעה על שטחיripחייבות להיות יחסיות,

זיכרון.

:ripהתוכנית הבאה נותנת איזה אינדיקציה על ערכו של

// print_rip3.c

#include <stdio.h>

extern unsigned long long int ret_rip();

extern unsigned long long int ret_rip2(unsigned long long int *rip2);

unsigned long long int lea1_rip, lea2_rip, stack_rip;unsigned long long int (*pf)(unsigned long long int *);

int main(){ lea1_rip = ret_rip(); pf = ret_rip; printf("lea1_rip = %llu, hex = %llx\n", lea1_rip, lea1_rip); printf("&ret_rip = %llu, hex = %llx\n", pf, pf); lea2_rip = ret_rip2(&stack_rip); pf = ret_rip2; printf("lea2_rip = %llu, hex = %llx\n", lea2_rip, lea2_rip); printf("&ret_rip2 = %llu, hex = %llx\n", pf, pf);

printf("stack_rip = %llu, hex = %llx\n", stack_rip, stack_rip); printf("main = %llu, hex = %llx\n", main, main); printf("&stack_rip = %llu, hex = %llx\n", &stack_rip, &stack_rip); printf("&lea1_rip = %llu, hex = %llx\n", &lea1_rip, &lea1_rip); printf("&lea2_rip = %llu, hex = %llx\n", &lea2_rip, &lea2_rip); printf("&pf = %llu, hex = %llx\n", &pf, &pf);

}//main

.file "RET_RIP.C"

.intel_syntax noprefix

.text

.globl ret_rip

.def ret_rip; .scl 2; .type 32; .endef

.seh_proc ret_ripret_rip:.LFB0:

pushrbp.seh_pushreg rbpmov rbp, rsp.seh_setframe rbp, 0.seh_endprologuelea rax, [rip]pop rbpret.seh_endproc.ident "GCC: (x86_64-posix-seh-rev1, Built by MinGW-

W64 project) 6.3.0"

.file "RET_RIP2.C"

.intel_syntax noprefix

.text

.globl ret_rip2

.def ret_rip2; .scl 2; .type 32; .endef

.seh_proc ret_rip2ret_rip2:.LFB0:

pushrbp.seh_pushreg rbpmov rbp, rsp.seh_setframe rbp, 0.seh_endprologuemov rax, QWORD PTR 8[rbp]mov [rcx], raxlea rax,0[rip]pop rbpret.seh_endproc.ident "GCC: (x86_64-posix-seh-rev1, Built by MinGW-

W64 project) 6.3.0"

פלט ריצה:D:\print_rip>gcc print_rip3.c ret_rip.s ret_rip2.s

D:\print_rip>a.exelea1_rip = 4200315, hex = 40177b&ret_rip = 4200304, hex = 401770lea2_rip = 4200338, hex = 401792&ret_rip2 = 4200320, hex = 401780stack_rip = 4199995, hex = 40163bmain = 4199856, hex = 4015b0&stack_rip = 4225392, hex = 407970

&lea1_rip = 4225408, hex = 407980&lea2_rip = 4225400, hex = 407978&pf = 4225416, hex = 407988

D:\print_rip>

פשוט אך יעיל. debuggerלמערכת ההרצה הבאה תמחיש את עיקר האמצעים הקיימים:

C:\Users\User\asm64>gcc -g call_id3.c idiv_mod64.s

C:\Users\User\academic\ComArchNew\asm64>gcc -g call_id3.c idiv_mod64.s

C:\Users\User\asm64>gdb a.exeGNU gdb (GDB) 7.11.1Copyright (C) 2016 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-w64-mingw32".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from a.exe...done.

(gdb) helpList of classes of commands:

aliases -- Aliases of other commandsbreakpoints -- Making program stop at certain pointsdata -- Examining datafiles -- Specifying and examining filesinternals -- Maintenance commandsobscure -- Obscure featuresrunning -- Running the programstack -- Examining the stackstatus -- Status inquiriessupport -- Support facilitiestracepoints -- Tracing of program execution without stopping the programuser-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.Type "help all" for the list of all commands.Type "help" followed by command name for full documentation.Type "apropos word" to search for commands related to "word".Command name abbreviations are allowed if unambiguous.(gdb) help breakpointsMaking program stop at certain points.

List of commands:

awatch -- Set a watchpoint for an expressionbreak -- Set breakpoint at specified locationbreak-range -- Set a breakpoint for an address rangecatch -- Set catchpoints to catch eventscatch assert -- Catch failed Ada assertionscatch catch -- Catch an exceptioncatch exception -- Catch Ada exceptionscatch exec -- Catch calls to execcatch fork -- Catch calls to fork

catch load -- Catch loads of shared librariescatch rethrow -- Catch an exceptioncatch signal -- Catch signals by their names and/or numberscatch syscall -- Catch system calls by their names and/or numberscatch throw -- Catch an exceptioncatch unload -- Catch unloads of shared librariescatch vfork -- Catch calls to vforkclear -- Clear breakpoint at specified locationcommands -- Set commands to be executed when a breakpoint is hitcondition -- Specify breakpoint number N to break only if COND is truedelete -- Delete some breakpoints or auto-display expressionsdelete bookmark -- Delete a bookmark from the bookmark listdelete breakpoints -- Delete some breakpoints or auto-display expressionsdelete display -- Cancel some expressions to be displayed when program stopsdelete mem -- Delete memory regiondelete tracepoints -- Delete specified tracepoints---Type <return> to continue, or q <return> to quit---q(gdb) help breakSet breakpoint at specified location.break [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]PROBE_MODIFIER shall be present if the command is to be placed in aprobe point. Accepted values are `-probe' (for a generic, automaticallyguessed probe type), `-probe-stap' (for a SystemTap probe) or`-probe-dtrace' (for a DTrace probe).LOCATION may be a linespec, address, or explicit location as describedbelow.

With no LOCATION, uses current execution address of the selectedstack frame. This is useful for breaking on return to a stack frame.

THREADNUM is the number from "info threads".CONDITION is a boolean expression.

Linespecs are colon-separated lists of location parameters, such assource filename, function name, label name, and line number.Example: To specify the start of a label named "the_top" in thefunction "fact" in the file "factorial.c", use"factorial.c:fact:the_top".

Address locations begin with "*" and specify an exact address in theprogram. Example: To specify the fourth byte past the start function"main", use "*main + 4".

Explicit locations are similar to linespecs but use an option/argumentsyntax to specify location parameters.Example: To specify the start of the label named "the_top" in thefunction "fact" in the file "factorial.c", use "-source factorial.c---Type <return> to continue, or q <return> to quit---q(gdb) list11 int No_Zero_Divide;1213 printf("\nEnter Numerator, Denominator\n:");14 scanf("%lld %lld",&Num, &Denom);15 No_Zero_Divide = idiv_mod64(Num,Denom,&Q,&Rem);16 if (No_Zero_Divide)17 printf("\n %lld div %lld = %lld, mod(%lld,%lld) = %lld\n",18 Num, Denom, Q, Num, Denom, Rem);19 else20 printf("\nError: Zero Divide.\n");(gdb) list 1813 printf("\nEnter Numerator, Denominator\n:");14 scanf("%lld %lld",&Num, &Denom);15 No_Zero_Divide = idiv_mod64(Num,Denom,&Q,&Rem);16 if (No_Zero_Divide)17 printf("\n %lld div %lld = %lld, mod(%lld,%lld) = %lld\n",18 Num, Denom, Q, Num, Denom, Rem);19 else20 printf("\nError: Zero Divide.\n");

2122 return 0;(gdb) break 15Breakpoint 1 at 0x401593: file call_id3.c, line 15.(gdb) runStarting program: C:\Users\User\academic\ComArchNew\asm64\a.exe[New Thread 5124.0x17fc][New Thread 5124.0x10c]

Enter Numerator, Denominator:10000000 99

Thread 1 hit Breakpoint 1, main () at call_id3.c:1515 No_Zero_Divide = idiv_mod64(Num,Denom,&Q,&Rem);(gdb) print Num$1 = 10000000(gdb) print Denom$2 = 99(gdb) stepidiv_mod64 () at idiv_mod64.s:88 push rbp(gdb) step10 mov rbp, rsp(gdb) step13 mov rbx,rdx(gdb) print $rbp$3 = (void *) 0x61fdd0(gdb) contContinuing.

10000000 div 99 = 101010, mod(10000000,99) = 10[Thread 5124.0x10c exited with code 0][Inferior 1 (process 5124) exited normally](gdb) quit

C:\Users\User\asm64>

top related