Division zweier 64 bit Zahlen mit 32 bit Registern
-
Der gcc erzeugt bei der Division einer ganzen 64 bit Zahl (long long int) auf 32-Bit-Systemen verschiedene externe Funktionen und baut den Code für die Division nicht direkt ein. Obwohl ich mir den Code der Funktionen in der libgcc2.c ansah, versteh ich ihn nicht ganz. Leider fand ich keine gute Erklärung, wieso das genau so gemacht wird.
Weiß jemand, wo ich Information zur Mathematik hinter dem Code finde?
-
Könntest du den Code auch mal posten? Nicht jeder hat einen 32-bit gcc zur Verfügung.
-
Wenn du amd64 hast schon, man muss ihn nur lieb bitten:
gcc -m32
-
Nun dann hier erstmal ohne Kommentar meinerseits der erzeugte Code:
long long int a=1234567890; long long int b=234567890; long long int c=a/b;
wird zu
8048434: 8d 4c 24 04 lea 0x4(%esp),%ecx 8048438: 83 e4 f0 and $0xfffffff0,%esp 804843b: ff 71 fc pushl -0x4(%ecx) 804843e: 55 push %ebp 804843f: 89 e5 mov %esp,%ebp 8048441: 51 push %ecx 8048442: 83 ec 34 sub $0x34,%esp 8048445: c7 45 f0 d2 02 96 49 movl $0x499602d2,-0x10(%ebp) 804844c: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp) 8048453: c7 45 e8 d2 38 fb 0d movl $0xdfb38d2,-0x18(%ebp) 804845a: c7 45 ec 00 00 00 00 movl $0x0,-0x14(%ebp) 8048461: 8b 45 e8 mov -0x18(%ebp),%eax 8048464: 8b 55 ec mov -0x14(%ebp),%edx 8048467: 89 44 24 08 mov %eax,0x8(%esp) 804846b: 89 54 24 0c mov %edx,0xc(%esp) 804846f: 8b 45 f0 mov -0x10(%ebp),%eax 8048472: 8b 55 f4 mov -0xc(%ebp),%edx 8048475: 89 04 24 mov %eax,(%esp) 8048478: 89 54 24 04 mov %edx,0x4(%esp) 804847c: e8 ff fe ff ff call 8048380 <__divdi3@plt> 8048481: 89 45 e0 mov %eax,-0x20(%ebp) 8048484: 89 55 e4 mov %edx,-0x1c(%ebp) 8048487: b8 00 00 00 00 mov $0x0,%eax 804848c: 83 c4 34 add $0x34,%esp 804848f: 59 pop %ecx 8048490: 5d pop %ebp 8048491: 8d 61 fc lea -0x4(%ecx),%esp 8048494: c3 ret
mit
08048370 <__divdi3@plt-0x10>: 8048370: ff 35 68 96 04 08 pushl 0x8049668 8048376: ff 25 6c 96 04 08 jmp *0x804966c 804837c: 00 00 add %al,(%eax) 08048380 <__divdi3@plt>: 8048380: ff 25 70 96 04 08 jmp *0x8049670 8048386: 68 00 00 00 00 push $0x0 804838b: e9 e0 ff ff ff jmp 8048370 <_init+0x30>
und
int a=1234; int b=234; int c=a/b;
wird zu
80483e4: 8d 4c 24 04 lea 0x4(%esp),%ecx 80483e8: 83 e4 f0 and $0xfffffff0,%esp 80483eb: ff 71 fc pushl -0x4(%ecx) 80483ee: 55 push %ebp 80483ef: 89 e5 mov %esp,%ebp 80483f1: 51 push %ecx 80483f2: 83 ec 10 sub $0x10,%esp 80483f5: c7 45 f8 d2 04 00 00 movl $0x4d2,-0x8(%ebp) 80483fc: c7 45 f4 ea 00 00 00 movl $0xea,-0xc(%ebp) 8048403: 8b 55 f8 mov -0x8(%ebp),%edx 8048406: 89 d0 mov %edx,%eax 8048408: c1 fa 1f sar $0x1f,%edx 804840b: f7 7d f4 idivl -0xc(%ebp) 804840e: 89 45 f0 mov %eax,-0x10(%ebp) 8048411: b8 00 00 00 00 mov $0x0,%eax 8048416: 83 c4 10 add $0x10,%esp 8048419: 59 pop %ecx 804841a: 5d pop %ebp 804841b: 8d 61 fc lea -0x4(%ecx),%esp 804841e: c3 ret 804841f: 90 nop
Edit: Nur, wie komme ich jetzt an __divdi3? Das ist irgendwo in einer Bibliothek...
Edit2: Ok, einfach die gelinkte Executable disassembliert, da steht divd3 dann drin.