21.2 乘法,除法

  1. #include <stdint.h>
  2. uint64_t f3 (uint64_t a, uint64_t b)
  3. {
  4. return a*b;
  5. };
  6. uint64_t f4 (uint64_t a, uint64_t b)
  7. {
  8. return a/b;
  9. };
  10. uint64_t f5 (uint64_t a, uint64_t b)
  11. {
  12. return a % b;
  13. };

代码 21.3: MSVC 2012 /Ox /Ob1

  1. _a$ = 8 ; size = 8
  2. _b$ = 16 ; size = 8
  3. _f3 PROC
  4. push DWORD PTR _b$[esp]
  5. push DWORD PTR _b$[esp]
  6. push DWORD PTR _a$[esp+8]
  7. push DWORD PTR _a$[esp+8]
  8. call __allmul ; long long multiplication
  9. ret 0
  10. _f3 ENDP
  11. _a$ = 8 ; size = 8
  12. _b$ = 16 ; size = 8
  13. _f4 PROC
  14. push DWORD PTR _b$[esp]
  15. push DWORD PTR _b$[esp]
  16. push DWORD PTR _a$[esp+8]
  17. push DWORD PTR _a$[esp+8]
  18. call __aulldiv ; unsigned long long division
  19. ret 0
  20. _f4 ENDP
  21. _a$ = 8 ; size = 8
  22. _b$ = 16 ; size = 8
  23. _f5 PROC
  24. push DWORD PTR _b$[esp]
  25. push DWORD PTR _b$[esp]
  26. push DWORD PTR _a$[esp+8]
  27. push DWORD PTR _a$[esp+8]
  28. call __aullrem ; unsigned long long remainder
  29. ret 0
  30. _f5 ENDP

乘法和除法是更为复杂的操作,一般来说,编译器会嵌入库函数的calls来使用。

部分函数的意义:可参见附录E。

Listing 21.4: GCC 4.8.1 -O3 -fno-inline

  1. _f3:
  2. push ebx
  3. mov edx, DWORD PTR [esp+8]
  4. mov eax, DWORD PTR [esp+16]
  5. mov ebx, DWORD PTR [esp+12]
  6. mov ecx, DWORD PTR [esp+20]
  7. imul ebx, eax
  8. imul ecx, edx
  9. mul edx
  10. add ecx, ebx
  11. add edx, ecx
  12. pop ebx
  13. ret
  14. _f4:
  15. sub esp, 28
  16. mov eax, DWORD PTR [esp+40]
  17. mov edx, DWORD PTR [esp+44]
  18. mov DWORD PTR [esp+8], eax
  19. mov eax, DWORD PTR [esp+32]
  20. mov DWORD PTR [esp+12], edx
  21. mov edx, DWORD PTR [esp+36]
  22. mov DWORD PTR [esp], eax
  23. mov DWORD PTR [esp+4], edx
  24. call ___udivdi3 ; unsigned division
  25. add esp, 28
  26. ret
  27. _f5:
  28. sub esp, 28
  29. mov eax, DWORD PTR [esp+40]
  30. mov edx, DWORD PTR [esp+44]
  31. mov DWORD PTR [esp+8], eax
  32. mov eax, DWORD PTR [esp+32]
  33. mov DWORD PTR [esp+12], edx
  34. mov edx, DWORD PTR [esp+36]
  35. mov DWORD PTR [esp], eax
  36. mov DWORD PTR [esp+4], edx
  37. call ___umoddi3 ; unsigned modulo
  38. add esp, 28
  39. ret

GCC的做法几乎一样,但是乘法代码内联在函数中,可认为这样更有效。

GCC有一些不同的库函数:参见附录D