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?


  • Mod

    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
    

  • Mod

    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.


Anmelden zum Antworten