Вы находитесь на странице: 1из 1033

Reverse Engineering

Reverse Engineering


<dennis(a)yurichev.com>

cbn d
2013-2015, .
Creative Commons Attribution-NonCommercial-NoDerivs
( ) 3.0 .
, http://creativecommons.org/licenses/by-nc-nd/3.0/.
(14 2015 .).
( ) beginners.re.
.
LITE- ( ),
reverse engineering: beginners.re
twitter : @yurichev1 ,
2 .
: facebook.
1 twitter.com/yurichev
2 yurichev.com

i
, !

http://beginners.re/survey.html

ii

I 1

II 469

III 478

IV Java 628

V 665

VI 688

VII 742

3
VIII RE - 748

IX (proprietary) 862

X 894

XI 912

XII 916

954

956

996

3 Reverse Engineering

iii

0.0.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi

I 1
1 CPU 3
1.1 ISA4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 5
2.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3.1 - MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3 Hello, world! 7
3.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.1.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.1.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.1.3 GCC: AT&T . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.1 MSVC x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.2 GCC x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.3 GCC - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.4 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.4.1 Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.4.2 Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.4.3 Xcode 4.6.3 (LLVM) ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.4.4 Xcode 4.6.3 (LLVM) ( Thumb-2) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.4.5 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.5 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.5.1 (global pointer) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.5.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.5.3 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.5.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.5.5 GCC: GDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.7.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.7.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

4 24
4.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

5 25
5.1 ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5.2 ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.2.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.2.4 x86: alloca() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.2.5 (Windows) SEH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.2.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4 Instruction Set Architecture ( )

iv

5.2.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.5.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.5.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

6 printf() 37
6.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.1.1 x86: 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.1.2 x64: 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
6.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.2.1 ARM: 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.2.2 ARM: 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.3.1 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.3.2 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
6.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

7 scanf() 61
7.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.1.2 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.1.3 MSVC + OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
7.1.4 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.1.5 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
7.1.6 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
7.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
7.2.1 MSVC: x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
7.2.2 MSVC: x86 + OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
7.2.3 GCC: x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
7.2.4 MSVC: x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
7.2.5 ARM: Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
7.2.6 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.2.7 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.3 scanf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7.3.1 MSVC: x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7.3.2 MSVC: x86: IDA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
7.3.3 MSVC: x86 + OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
7.3.4 MSVC: x86 + Hiew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7.3.5 MSVC: x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
7.3.6 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
7.3.7 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
7.3.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
7.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
7.4.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

8 91
8.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
8.1.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
8.1.2 MSVC + OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
8.1.3 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
8.2 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
8.2.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
8.2.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
8.2.3 GCC: uint64_t int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
8.3 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
8.3.1 Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
8.3.2 Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.3.3 Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.3.4 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

v

9 101
9.1 void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
9.2 ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
9.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

10 104
10.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
10.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
10.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

11 GOTO 114
11.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
11.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

12 118
12.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
12.1.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
12.1.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
12.1.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
12.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
12.2.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
12.2.2 Keil 6/2013: Thumb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
12.2.3 Keil 6/2013: ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
12.2.4 GCC 4.9 (ARM64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
12.2.5 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
12.2.6 ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
12.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
12.3.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
12.3.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
12.3.3 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
12.3.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
12.3.5 , if/else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
12.3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
12.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
12.4.1 32-bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
12.4.2 64-bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
12.4.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
12.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
12.5.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
12.5.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
12.5.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
12.5.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
12.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

13 switch()/case/default 147
13.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
13.1.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
13.1.2 ARM: Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
13.1.3 ARM: Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
13.1.4 ARM64: GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
13.1.5 ARM64: GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
13.1.6 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
13.1.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
13.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
13.2.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
13.2.2 ARM: Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
13.2.3 ARM: Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
13.2.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
13.2.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
13.3 case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
13.3.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
13.3.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
13.3.3 ARM64: GCC 4.9.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
13.4 Fall-through . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
13.4.1 MSVC x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

vi

13.4.2 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
13.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
13.5.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

14 178
14.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
14.1.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
14.1.2 x86: OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
14.1.3 x86: tracer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
14.1.4 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
14.1.5 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
14.1.6 - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
14.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
14.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
14.2.2 ARM ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
14.2.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
14.2.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
14.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
14.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
14.4.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
14.4.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
14.4.3 #3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
14.4.4 #4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

15 - 197
15.1 strlen() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
15.1.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
15.1.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
15.1.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
15.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
15.2.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

16 210
16.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
16.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
16.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
16.1.3 , . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
16.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
16.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
16.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
16.3.1 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216

17 FPU 217
17.1 IEEE 754 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
17.2 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
17.3 ARM, MIPS, x86/x64 SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
17.4 /++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
17.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
17.5.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
17.5.2 ARM: Xcode 4.6.3 (LLVM) ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
17.5.3 ARM: Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
17.5.4 ARM64: GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
17.5.5 ARM64: GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
17.5.6 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
17.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
17.6.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
17.6.2 ARM + Xcode 4.6.3 (LLVM) ( Thumb-2) . . . . . . . . . . . . . . . . . . . . . . . 229
17.6.3 ARM + Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
17.6.4 ARM64 + GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
17.6.5 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
17.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
17.7.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
17.7.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
17.7.3 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
17.7.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264

vii

17.8 , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
17.9 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
17.10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
17.10.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
17.10.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264

18 267
18.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
18.1.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
18.1.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
18.1.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
18.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
18.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
18.2.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
18.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
18.3.1 Xcode 4.6.3 (LLVM) ( Thumb-2) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
18.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
18.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
18.5.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
18.5.2 32- ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
18.5.3 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
18.5.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
18.5.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
18.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
18.6.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
18.6.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
18.6.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
18.6.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
18.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
18.7.1 32-bit ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300
18.7.2 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
18.7.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
18.7.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
18.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
18.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
18.9.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
18.9.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
18.9.3 #3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
18.9.4 #4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
18.9.5 #5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311

19 316
19.1 - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
19.1.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
19.1.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
19.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
19.2.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
19.2.2 ARM + Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
19.2.3 ARM + Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
19.2.4 ARM + Xcode 4.6.3 (LLVM) ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
19.2.5 ARM: BIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
19.2.6 ARM64: GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
19.2.7 ARM64: GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
19.2.8 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
19.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
19.4 : FPU5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
19.4.1 - XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
19.4.2 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
19.4.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
19.4.4 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
19.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
19.5.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
19.5.2 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
5 Floating-point unit

viii

19.5.3 ARM + Xcode 4.6.3 (LLVM) ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
19.5.4 ARM + Xcode 4.6.3 (LLVM) ( Thumb-2) . . . . . . . . . . . . . . . . . . . . . . . . . 344
19.5.5 ARM64 + GCC 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
19.5.6 ARM64 + GCC 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
19.5.7 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
19.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
19.6.1 ( ) . . . . . . . . . . . . . . . . . . . . . 347
19.6.2 ( ) . . . . . . . . . . . . . . . . . . . . . . 347
19.6.3 ( ) . . . . . . . . . . . . . . . . . . . . . 348
19.6.4 ( ) . . . . . . . . . . . . . . . . . . . . . . 348
19.6.5 ( ) . . . . . . . . . . . . . . . . . . . . . . . . 348
19.6.6 ( ) . . . . . . . . . . . . . . . . . . . . . . . . . 349
19.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
19.7.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
19.7.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
19.7.3 #3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
19.7.4 #4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353

20 356
20.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
20.2 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
20.3 32-bit ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
20.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
20.4.1 MIPS (relocs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
20.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361

21 362
21.1 MSVC: SYSTEMTIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
21.1.1 OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
21.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
21.2 malloc() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
21.3 UNIX: struct tm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
21.3.1 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
21.3.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
21.3.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
21.3.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
21.3.5 32- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
21.3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
21.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
21.4.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
21.4.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
21.4.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
21.4.4 - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
21.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
21.5.1 OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
21.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
21.6.1 CPUID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
21.6.2 oat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
21.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
21.7.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
21.7.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

22 (union) 398
22.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
22.1.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
22.1.2 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
22.1.3 ARM ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
22.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
22.2.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
22.2.2 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
22.2.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
22.2.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
22.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404

ix

23 406
23.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
23.1.1 MSVC + OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
23.1.2 MSVC + tracer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
23.1.3 MSVC + tracer (code coverage) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
23.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
23.2.1 GCC + GDB ( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
23.2.2 GCC + GDB ( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415

24 64- 32- 418


24.1 64- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
24.1.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
24.1.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
24.1.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
24.2 , , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
24.2.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
24.2.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
24.2.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
24.3 , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
24.3.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
24.3.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
24.3.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
24.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
24.4.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
24.4.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
24.4.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
24.5 32- 64- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
24.5.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
24.5.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
24.5.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428

25 SIMD 429
25.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
25.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
25.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435
25.2 strlen() SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439

26 64 443
26.1 x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
26.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
26.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450

27 SIMD 451
27.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
27.1.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
27.1.2 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
27.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
27.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
27.3.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
27.3.2 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
27.4 : x64 SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
27.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462
27.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462

28 - ARM 464
28.1 (#) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
28.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
28.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
28.3.1 32- ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
28.3.2 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
28.4 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466

29 - MIPS 468
29.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
29.2 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468

x

II 469
30 471

31 Endianness ( ) 473
31.1 Big-endian ( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
31.2 Little-endian ( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
31.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
31.4 Bi-endian ( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
31.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474

32 475

33 CPU 476
33.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476
33.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476

34 - 477
34.1 ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477

III 478
35 479
35.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
35.1.1 MSVC 2012 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
35.1.2 MSVC 2012 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
35.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481

36 484
36.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
36.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
36.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490

37 CRC32 491

38 494
38.1 calc_network_address() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
38.2 form_IP() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
38.3 print_as_IP() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
38.4 form_netmask() set_bit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
38.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499

39 : 500
39.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500
39.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501
39.3 Intel C++ 2011 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502

40 Duffs device 505

41 9 508
41.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
41.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
41.2.1 Xcode 4.6.3 (LLVM) ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
41.2.2 Xcode 4.6.3 (LLVM) ( Thumb-2) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
41.2.3 Xcode 4.6.3 (LLVM) Keil 6/2013 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
41.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
41.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
41.4.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512
41.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512
41.5.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512
41.5.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513
41.6 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513

42 (atoi()) 515
42.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515

xi

42.1.1 MSVC 2013 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
42.1.2 GCC 4.9.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
42.1.3 Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
42.1.4 Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
42.1.5 GCC 4.9.1 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
42.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518
42.2.1 GCC 4.9.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519
42.2.2 Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520
42.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521

43 Inline- 522
43.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
43.1.1 strcmp() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
43.1.2 strlen() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525
43.1.3 strcpy() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525
43.1.4 memset() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525
43.1.5 memcpy() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
43.1.6 memcmp() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
43.1.7 IDA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530

44 C99 restrict 531

45 abs() 534
45.1 GCC 4.9.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534
45.2 GCC 4.9 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535

46 (variadic) 536
46.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
46.1.1 cdecl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
46.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
46.2 vprintf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539

47 541
47.1 x64: MSVC 2013 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
47.2 x64: GCC 4.9.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
47.3 x64: GCC 4.9.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
47.4 ARM64: GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
47.5 ARM64: GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
47.6 ARM: Keil 6/2013 ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
47.7 ARM: Keil 6/2013 ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
47.8 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548

48 toupper() 550
48.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
48.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
48.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
48.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552
48.2.1 GCC ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552
48.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553

49 554
49.1 (x86) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554
49.2 ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555

50 559
50.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559
50.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560
50.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560
50.2.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560
50.2.3 / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560
50.2.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
50.2.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
50.3 / - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
50.4 - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
50.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562

xii

50.5.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562

51 ++ 563
51.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563
51.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563
51.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569
51.1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572
51.1.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573
51.1.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
51.2 ostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
51.3 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
51.4 STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
51.4.1 std::string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
51.4.2 std::list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587
51.4.3 std::vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
51.4.4 std::map std::set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603

52 614

53 Windows 16-bit 617


53.1 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617
53.2 #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617
53.3 #3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618
53.4 #4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619
53.5 #5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621
53.6 #6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625
53.6.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626

IV Java 628
54 Java 629
54.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
54.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
54.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
54.4 JVM6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636
54.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636
54.6 beep() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638
54.7 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638
54.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
54.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641
54.10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642
54.11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
54.12switch() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645
54.13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
54.13.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
54.13.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647
54.13.3 main() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647
54.13.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648
54.13.5 - (variadic) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 650
54.13.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
54.13.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652
54.13.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653
54.14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653
54.14.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653
54.14.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654
54.15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655
54.16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 658
54.17 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660
54.17.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660
54.17.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 662
54.18 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 664
6 Java virtual machine
7

xiii

V 665
55 667
55.1 Microsoft Visual C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
55.1.1 Name mangling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
55.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
55.2.1 Name mangling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
55.2.2 Cygwin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
55.2.3 MinGW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667
55.3 Intel FORTRAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
55.4 Watcom, OpenWatcom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
55.4.1 Name mangling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
55.5 Borland . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
55.5.1 Delphi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
55.6 DLL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669

56 (win32) 670
56.1 Windows API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670
56.2 tracer: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671

57 672
57.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
57.1.1 /++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
57.1.2 Borland Delphi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
57.1.3 Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673
57.1.4 Base64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
57.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
57.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676

58 assert() 677

59 678
59.1 Magic numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 678
59.1.1 DHCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679
59.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679

60 680

61 682
61.1 XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 682
61.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 682

62 magic numbers 684

63 685
63.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685
63.2 ++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685
63.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685
63.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686
63.4.1 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687
63.4.2 - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687

VI 688
64 689
64.1 cdecl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 689
64.2 stdcall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 689
64.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 690
64.3 fastcall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 690
64.3.1 GCC regparm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
64.3.2 Watcom/OpenWatcom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
64.4 thiscall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
64.5 x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
64.5.1 Windows x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
64.5.2 Linux x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 694

xiv

64.6 oat, double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 694
64.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 694
64.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 695

65 Thread Local Storage 697


65.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697
65.1.1 Win32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697
65.1.2 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701

66 (syscall-) 702
66.1 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 702
66.2 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703

67 Linux 704
67.1 - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704
67.1.1 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706
67.2 LD_PRELOAD Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706

68 Windows NT 709
68.1 CRT (win32) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709
68.2 Win32 PE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712
68.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712
68.2.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713
68.2.3 Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713
68.2.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713
68.2.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714
68.2.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714
68.2.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715
68.2.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717
68.2.9 .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717
68.2.10TLS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718
68.2.11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718
68.2.12Further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718
68.3 Windows SEH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718
68.3.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718
68.3.2 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 723
68.3.3 Windows x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 736
68.3.4 SEH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 739
68.4 Windows NT: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 740

VII 742
69 743
69.1 IDA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 743

70 744
70.1 OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 744
70.2 GDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 744
70.3 tracer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 744

71 745
71.0.1 strace / dtruss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745

72 746

73 747

VIII RE- 748


74 task manager (Windows Vista) 750
74.1 LEA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 752

75 Color Lines 754

xv

76 (Windows XP) 758
76.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 762

77 + SMT- Z3 763
77.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 763
77.2 Z3 SMT- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766

78 771
78.1 #1: MacOS Classic PowerPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 771
78.2 #2: SCO OpenServer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 778
78.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 785
78.3 #3: MS-DOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787

79 QR9: , 793

80 SAP 820
80.1 SAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 820
80.2 SAP 6.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 830

81 Oracle RDBMS 834


81.1 V$VERSION Oracle RDBMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 834
81.2 X$KSMLRU Oracle RDBMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 841
81.3 V$TIMER Oracle RDBMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 843

82 847
82.1 EICAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847

83 849
83.1 10 PRINT CHR$(205.5+RND(1)); : GOTO 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 849
83.1.1 42- Trixter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 849
83.1.2 Trixter: 27 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 850
83.1.3 . . . . . . . . . . . . . . . 850
83.1.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 851
83.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 852
83.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 853
83.2.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 858
83.2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 860

IX (proprietary) 862
84 XOR- 863
84.1 Norton Guide: XOR- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 864
84.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 865
84.2 XOR- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 867
84.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 870

85 Millenium 871

86 Oracle RDBMS: .SYM- 878

87 Oracle RDBMS: .MSB- 888


87.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 893

X 894
88 npad 895

89 897
89.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 897
89.2 x86- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 897

90 Compiler intrinsic 898

91 899

xvi

92 OpenMP 900
92.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 902
92.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 903

93 Itanium 906

94 8086 909

95 basic block- 910


95.1 Prole-guided optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 910

XI 912
96 913
96.1 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913
96.2 /++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913
96.3 x86 / x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913
96.4 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913
96.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913

97 914
97.1 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 914

98 915

XII 916
99 1 919
99.1 1.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 919

100 2 920
100.1 2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 920
100.1.1 MSVC 2010 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 920
100.1.2 MSVC 2012 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921
100.2 2.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921
100.2.1 MSVC 2010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921
100.2.2GCC 4.4.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 922
100.2.3 Keil ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 923
100.2.4 Keil ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 924
100.2.5 GCC 4.9.1 (ARM64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 924
100.2.6 GCC 4.4.5 (MIPS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 925
100.3 2.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 926
100.3.1 MSVC 2010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 926
100.3.2 Keil ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 927
100.3.3 Keil ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 927
100.3.4 GCC 4.9.1 (ARM64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 928
100.3.5 GCC 4.4.5 (MIPS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 929
100.4 2.13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 929
100.4.1 MSVC 2012 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 929
100.4.2Keil ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 930
100.4.3Keil ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 930
100.4.4 GCC 4.9.1 (ARM64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 930
100.4.5 GCC 4.4.5 (MIPS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 930
100.5 2.14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 931
100.5.1MSVC 2012 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 931
100.5.2Keil ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 932
100.5.3GCC 4.6.3 for Raspberry Pi ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 932
100.5.4 GCC 4.9.1 (ARM64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 933
100.5.5 GCC 4.4.5 (MIPS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 934
100.6 2.15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 935
100.6.1 MSVC 2012 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 935
100.6.2 GCC 4.4.6 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 938
100.6.3 GCC 4.8.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 938
100.6.4Keil ( ARM): Cortex-R4F . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 939

xvii

100.6.5 GCC 4.9.1 (ARM64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 940
100.6.6 GCC 4.4.5 (MIPS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 941
100.7 2.16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 942
100.7.1 MSVC 2012 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 942
100.7.2 Keil ( ARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 943
100.7.3 Keil ( Thumb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 943
100.7.4 GCC 4.9.1 (ARM64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 943
100.7.5 GCC 4.9.1 (ARM64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 944
100.7.6 GCC 4.4.5 (MIPS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 947
100.8 2.17 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 948
100.9 2.18 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 948
100.10
2.19 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 948
100.11
2.20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 948

101 3 950
101.1 3.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 950
101.2 3.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 950
101.3 3.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 950
101.4 3.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 950
101.5 3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 951
101.6 3.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 951

102crackme / keygenme 952

954
103? 954

956
A x86 956
A.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 956
A.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 956
A.2.1 RAX/EAX/AX/AL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 956
A.2.2 RBX/EBX/BX/BL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957
A.2.3 RCX/ECX/CX/CL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957
A.2.4 RDX/EDX/DX/DL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957
A.2.5 RSI/ESI/SI/SIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957
A.2.6 RDI/EDI/DI/DIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957
A.2.7 R8/R8D/R8W/R8L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957
A.2.8 R9/R9D/R9W/R9L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958
A.2.9 R10/R10D/R10W/R10L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958
A.2.10 R11/R11D/R11W/R11L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958
A.2.11 R12/R12D/R12W/R12L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958
A.2.12 R13/R13D/R13W/R13L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958
A.2.13 R14/R14D/R14W/R14L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958
A.2.14 R15/R15D/R15W/R15L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958
A.2.15 RSP/ESP/SP/SPL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959
A.2.16 RBP/EBP/BP/BPL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959
A.2.17 RIP/EIP/IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959
A.2.18 CS/DS/ES/SS/FS/GS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959
A.2.19 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959
A.3 FPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 960
A.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 960
A.3.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 961
A.3.3 Tag Word . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 961
A.4 SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 962
A.4.1 MMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 962
A.4.2 SSE AVX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 962
A.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 962
A.5.1 DR6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 962
A.5.2 DR7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 962
A.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 963

xviii

A.6.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 963
A.6.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 964
A.6.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 968
A.6.4 FPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 972
A.6.5 ASCII- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 973

B ARM 975
B.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 975
B.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 975
B.3 32- ARM (AArch32) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 975
B.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 975
B.3.2 Current Program Status Register (CPSR) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976
B.3.3 VPF ( ) NEON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976
B.4 64- ARM (AArch64) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976
B.4.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976
B.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 977
B.5.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 977

C MIPS 978
C.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 978
C.1.1 GPR8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 978
C.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . 978
C.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 978
C.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 979

D GCC 980

E MSVC 981

F Cheatsheets 982
F.1 IDA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 982
F.2 OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 982
F.3 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 983
F.4 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 983
F.5 GDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 983

G 985
G.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 985
G.1.1 Hello, world! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 985
G.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 985
G.1.3 scanf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 986
G.1.4 switch()/case/default . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 986
G.1.5 #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 986
G.1.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 986
G.1.7 #3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 986
G.1.8 #4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 987
G.1.9 - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 987
G.1.10 . . . . . . . . . . . . . . . . . . . . . . . . . 987
G.1.11 FPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 987
G.1.12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 988
G.1.13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 989
G.1.14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 990
G.1.15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 991
G.1.16 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 991
G.2 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992
G.2.1 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992
G.2.2 1.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992
G.3 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992
G.3.1 2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992
G.3.2 2.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992
G.3.3 2.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 992
G.3.4 2.13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993
G.3.5 2.14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993
G.3.6 2.15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993
8 General Purpose Registers ( )

xix

G.3.7 2.16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993
G.3.8 2.17 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993
G.3.9 2.18 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993
G.3.10 2.19 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993
G.3.11 2.20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.4 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.4.1 3.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.4.2 3.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.4.3 3.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.4.4 3.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.4.5 3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.4.6 3.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
G.5.1 (Windows XP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994

996
1000

1002

xx

reverse engineering : 1) ; 2) -
; 3) .
.

x86/x64, ARM/ARM64, MIPS, Java/JVM.

Oracle RDBMS (81 (. 834)), Itanium (93 (. 906)), (78 (. 771)), LD_PRELOAD (67.2
(. 706)), , ELF9 , PE win32 (68.2 (. 712)), x86-64 (26.1 (. 443)),
(68.4 (. 740)), (66 (. 702)), TLS10 , - (PIC11 ) (67.1 (. 704)), prole-
guided optimization (95.1 (. 910)), C++ STL (51.4 (. 580)), OpenMP (92 (. 900)), SEH (68.3 (. 718)).

reverse engineer . -
: dennis(a)yurichev.com, Skype: dennis.yurichev.

, : herm1t , Avid .
, : Beaver , , Shell
Rocket, Zhu Ruijin, Changmin Heo.
: , Arnaud Patard (rtp #debian-arm IRC), .
: Archer.
: Byungho Min.
: Lstar , , , Logxen , Yuan Jochen Kang,
Mal Malakov, Lewis Porter.
.
: .
github.com .
LATEX. .
9 , Linux *NIX
10 Thread Local Storage
11 Position Independent Code: 67.1 (. 704)

xxi

0.0.1.

, () .
, , 12 (LaTeX),
.
.
: PLANS13 .
, , .
http://yurichev.com/donate.html.
!

http://yurichev.com/donors.html.

mini-

Q: ?
A: 14 , : -
15 . , CPU16
. - ,
: 1) malware () ; 2) -
. , ,
, , , .

Q: PDF-, ?
A: Adobe Acrobat Reader Alt+LeftArrow.

Q: ! ?
A: lite-: http://beginners.re/#lite.

Q: , reverse engineering-.
A: , LITE- 1-2 .

Q: ? ?
A: , Creative Commons. -
, .

Q: .
A: .

Q: reverse engineer-?
A: reddit, RE17 , hiring thread (2013 Q3, 2014). .
netsec : 2014 Q2.

Q: ?
A: : ; .

Q: ...
A: (dennis(a)yurichev.com) : forum.yurichev.com.

Reverse Engineering

Its very well done .. and for free .. amazing.18 Daniel Bilar, Siege Technologies, LLC.
12 github.com/dennis714/RE-for-beginners
13 github.com/dennis714/RE-for-beginners/blob/master/PLANS
14
15 : [Fog13b]
16 Central processing unit
17 reddit.com/r/ReverseEngineering/
18 twitter.com/daniel_bilar/status/436578617221742593

xxii

... excellent and free19 Pete Finnigan, Oracle RDBMS.
... book is interesting, great job! Michael Sikorski, Practical Malware Analysis: The Hands-On Guide to
Dissecting Malicious Software.
... my compliments for the very nice tutorial! Herbert Bos, Vrije Universiteit Amsterdam,
Modern Operating Systems (4th Edition).
... It is amazing and unbelievable. Luis Rocha, CISSP / ISSAP, Technical Manager, Network & Information Security at
Verizon Business.
Thanks for the great work and your book. Joris van de Vis, SAP Netweaver & Security.
... reasonable intro to some of the techniques.20 Mike Stay, Federal Law Enforcement Training
Center, Georgia, US.
I love this book! I have several students reading it at the moment, plan to use it in graduate course.21 ,
Research Assistant Professor Computer Science Dartmouth College
Dennis @Yurichev has published an impressive (and free!) book on reverse engineering22 Tanel Poder,
Oracle RDBMS.
This book is some kind of Wikipedia to beginners... Archer, Chinese Translator, IT Security Researcher.
, .
, DefCon-UA

2015, Acorn (
2014) .
.
Byungho Min (twitter/tais9).
: facebook/andydinka.
.
,
.

19 twitter.com/petennigan/status/400551705797869568
20 reddit
21 twitter.com/sergeybratus/status/505590326560833536
22 twitter.com/TanelPoder/status/524668104065159169

xxiii
I

, ++, , ,
. 23 . ,
/++ , , .
, , , .
- .
, ( )
.

,
, . ,
(
), .
. .


.
, .
.
, ( ) . -
( )
.
-
, , .
,
. ,
.
reverse engineer ,
, . .

23 , , , .

2
1. CPU 1. CPU

CPU

CPU .
:
: CPU. : , ,
. , CPU (ISA).
: CPU. .
: , : ,
, ..
CPU : CPU (GPR). 8 x86, 16
x86-64, 16 ARM. . ,
1 8 32 ( 64) .
!
?
/++, Java, Python, CPU . ,
CPU , . ,
- , , .
, 2 .

1.1. ISA
x86 , 64- , x64
ISA. x86 , 16- 8086 -
.

ARM RISC3 - ,
. ARM 4- 4 . ,
ARM.
, . , 5
c .
ISA Thumb, 2- .
Thumb. ARM , Thumb -
. , ARM Thumb .
ARM , Thumb : Thumb-2 ( ARMv7). Thumb-2
, 4 . ,
Thumb-2 ARM Thumb. . Thumb-2 -
ARM.
iPod/iPhone/iPad Thumb-2, Xcode .
64- ARM. ISA 4- , Thumb. 64-
1
2 .
3 Reduced instruction set computing
4 , , ( ) .

switch() (13.2.2 (. 167)).


5 MOV/PUSH/CALL/Jcc

3
1. CPU 1. CPU
ISA, 3 ARM: ARM, Thumb ( Thumb-
2) ARM64. , , ,
. , ARM ISA.
RISC ISA 32- MIPS, PowerPC Alpha
AXP.

4
2. 2.

, :
, :

2.1: /++
int f()
{
return 123;
};

2.1. x86
GCC:

2.2: GCC/MSVC ( )
f:
mov eax, 123
ret

MSVC
. 123 EAX, -
. RET, .
EAX.

2.2. ARM
ARM?

2.3: Keil 6/2013 ( ARM) ASM Output


f PROC
MOV r0,#0x7b ; 123
BX lr
ENDP

ARM R0 , 123 R0.


(RA1 ) ARM , LR2 . BX LR
, -.
, MOV x86 ARM . , ,
.
1
2 Link Register

5
2. 2.
2.3. MIPS
MIPS. ( $0 $31) ($V0, $A0, ..).
GCC :

2.4: GCC 4.4.5 ( )


j $31
li $2,123 # 0x7b

IDA3 :

2.5: GCC 4.4.5 (IDA)


jr $ra
li $v0, 0x7B

$2 ( $V0) . LI Load Immediate .


(J JR), -,
$31 ( $RA). LR ARM.
(LI) (J JR) ? RISC
branch delay slot. , . : MIPS
. ,
, .

2.3.1. - MIPS

MIPS .
, ISA .

3 , Hex-Rays

6
3. HELLO, WORLD! 3. HELLO, WORLD!

Hello, world!

, The C programming Language[Ker88]:


#include <stdio.h>

int main()
{
printf("hello, world\n");
return 0;
}

3.1. x86

3.1.1. MSVC

MSVC 2010:
cl 1.cpp /Fa1.asm

( /Fa )

3.1: MSVC 2010


CONST SEGMENT
$SG3830 DB 'hello, world', 0AH, 00H
CONST ENDS
PUBLIC _main
EXTRN _printf:PROC
; Function compile flags: /Odtp
_TEXT SEGMENT
_main PROC
push ebp
mov ebp, esp
push OFFSET $SG3830
call _printf
add esp, 4
xor eax, eax
pop ebp
ret 0
_main ENDP
_TEXT ENDS

MSVC Intel. Intel AT&T :


3.1.3 (. 9).
1.obj, 1.exe.
: CONST ( -) _TEXT ( ).
hello, world /++ const char[] [Str13, p176, 7.3.2], .
- , $SG3830.
:

7
3. HELLO, WORLD! 3. HELLO, WORLD!

#include <stdio.h>

const char $SG3830[]="hello, world\n";

int main()
{
printf($SG3830);
return 0;
}

. ,
/++ . : 57.1.1 (. 672).
_TEXT : main(). main(), ,
1 .
printf() : CALL _printf. ( )
PUSH .
, printf() main(), ( )
. , ( ESP) .
ADD ESP, 4 4 ESP. 4? 32- ,
4 . x64- 8 . ADD ESP, 4 POP , -
2 .
, , Intel C++ Compiler, ADD POP ECX
( , , Oracle RDBMS, ), ,
ECX. , POP ECX, (1
POP 3 ADD).
POP ADD Oracle RDBMS:

3.2: Oracle RDBMS 10.2 Linux ( app.o)


.text:0800029A push ebx
.text:0800029B call qksfroChild
.text:080002A0 pop ecx

printf() /++ return 0 0 -


main(). XOR EAX, EAX. XOR,
3 , MOV EAX, 0 ,
(2 XOR 5 MOV).
SUB EAX, EAX, EAX EAX,
0 .
RET . /++ CRT4 , -
, , .

3.1.2. GCC

GCC 4.4.1 Linux: gcc 1.c -o 1 IDA


main(). IDA, MSVC, Intel5 .

3.3: IDA
main proc near

var_10 = dword ptr 10h

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 10h
mov eax, offset aHelloWorld ; "hello, world\n"
1 (4 (. 24)).
2 , ,
3 wikipedia
4 C runtime library : 68.1 (. 709)
5 GCC -S -masm=intel.

8
3. HELLO, WORLD! 3. HELLO, WORLD!
mov [esp+10h+var_10], eax
call _printf
mov eax, 0
leave
retn
main endp

. hello, world, , EAX, -


. AND ESP, 0FFFFFFF0h ESP
16- , (
, 4 16)6 .
SUB ESP, 10h 16 . , , 4.
, 16- .
( ) PUSH. var_10 -
printf(). .
printf().
MSVC, GCC MOV EAX, 0
.
LEAVE MOV ESP, EBP POP EBP
EBP . , .. ESP
EBP ( MOV EBP, ESP / AND ESP, ).

3.1.3. GCC: AT&T

, AT&T . -
UNIX-.
3.4: GCC 4.7.3
gcc S 1_1.c

:
3.5: GCC 4.7.3
.file "1_1.c"
.section .rodata
.LC0:
.string "hello, world\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, 8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $16, %esp
subl $16, %esp
movl $.LC0, (%esp)
call printf
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .main
.ident "GCC: (Ubuntu/Linaro 4.7.31ubuntu1) 4.7.3"
.section .note.GNUstack,"",@progbits

6 Wikipedia:

9
3. HELLO, WORLD! 3. HELLO, WORLD!
( ). . , ,
( .string, ,
). 7 :
3.6: GCC 4.7.3
.LC0:
.string "hello, world\n"
main:
pushl %ebp
movl %esp, %ebp
andl $16, %esp
subl $16, %esp
movl $.LC0, (%esp)
call printf
movl $0, %eax
leave
ret

Intel AT&T :
.
Intel-: <> < > <->.
AT&T-: <> <-> < >.
, : Intel
(=) , AT&T
() 8 .
AT&T: (%), ($).
.
AT&T: , :
q quad (64 )
l long (32 )
w word (16 )
b byte (8 )
: , IDA. : 0FFFFFFF0h
$-16. : 16 0x10 . -0x10
0xFFFFFFF0 ( 32- ).
0 MOV, XOR. MOV
. ( , ). -
LOAD STORE - .

3.2. x86-64

3.2.1. MSVC x86-64

64- MSVC:
3.7: MSVC 2012 x64
$SG2989 DB 'hello, world', 0AH, 00H

main PROC
sub rsp, 40
lea rcx, OFFSET FLAT:$SG2989
call printf
xor eax, eax
add rsp, 40
ret 0
main ENDP

7 , , GCC: -fno-asynchronous-unwind-tables
8 , (, memcpy(), strcpy()) -
Intel: , -.

10
3. HELLO, WORLD! 3. HELLO, WORLD!
x86-64 64- R-.
( , ), -
(fastcall: 64.3 (. 690)). ..
. Win64 4 RCX, RDX, R8, R9.
: printf() , RCX.
64-, 64- ( R-).
32 E-.
RAX/ EAX/ AX/ AL x86-64:
7 ( ) 6 5 4 3 2 1 0
RAXx64
EAX
AX
AH AL
main() int, /++, -
, 32-. main() RAX, EAX, .. 32- .
, 40 . shadow space, :
8.2.1 (. 94).

3.2.2. GCC x86-64

GCC 64- Linux:

3.8: GCC 4.4.6 x64


.string "hello, world\n"
main:
sub rsp, 8
mov edi, OFFSET FLAT:.LC0 ; "hello, world\n"
xor eax, eax ;
call printf
xor eax, eax
add rsp, 8
ret

Linux, *BSD Mac OS X x86-64 [Mit13]. 6


RDI, RSI, RDX, RCX, R8, R9, .
EDI (32- ). 64- , RDI?
64- MOV, - 32-
, 32-[Int13]. , MOV EAX, 011223344h
RAX, .
IDA (.o), 9 :

3.9: GCC 4.4.6 x64


.text:00000000004004D0 main proc near
.text:00000000004004D0 48 83 EC 08 sub rsp, 8
.text:00000000004004D4 BF E8 05 40 00 mov edi, offset format ; "hello, world\n"
.text:00000000004004D9 31 C0 xor eax, eax
.text:00000000004004DB E8 D8 FE FF FF call _printf
.text:00000000004004E0 31 C0 xor eax, eax
.text:00000000004004E2 48 83 C4 08 add rsp, 8
.text:00000000004004E6 C3 retn
.text:00000000004004E6 main endp

, , EDI 0x4004D4, 5 . ,
64- RDI, 7 . , GCC . , , ,
, , 4GiB.
EAX printf(). -
*NIX x86-64 EAX : with variable
arguments passes information about the number of vector registers used [Mit13].
9 Options Disassembly Number of opcode bytes

11
3. HELLO, WORLD! 3. HELLO, WORLD!
3.3. GCC -
, - const (3.1.1 (. 7)), , -
(immutable), : -
.
:
#include <stdio.h>

int f1()
{
printf ("world\n");
}

int f2()
{
printf ("hello world\n");
}

int main()
{
f1();
f2();
}

/++ ( MSVC) , GCC 4.8.1:

3.10: GCC 4.8.1 + IDA


f1 proc near

s = dword ptr 1Ch

sub esp, 1Ch


mov [esp+1Ch+s], offset s ; "world\n"
call _puts
add esp, 1Ch
retn
f1 endp

f2 proc near

s = dword ptr 1Ch

sub esp, 1Ch


mov [esp+1Ch+s], offset aHello ; "hello "
call _puts
add esp, 1Ch
retn
f2 endp

aHello db 'hello '


s db 'world',0xa,0

, , puts(),
f2(), , . ,
, .
puts() f1(), world . puts() ,
- !
( GCC) .

3.4. ARM
ARM :
embedded- Keil Release 6/2013.

12
3. HELLO, WORLD! 3. HELLO, WORLD!
Apple Xcode 4.6.3 ( LLVM-GCC 4.210 ).
GCC 4.9 (Linaro) ( ARM64), win32 http://go.yurichev.com/
17325.
, , 32- ARM ( Thumb Thumb-2).
64- ARM, ARM64.

3.4.1. Keil 6/2013 ( ARM)

Keil:
armcc.exe arm c90 O0 1.c

armcc Intel. -
, ARM11 , ,
IDA.
3.11: Keil 6/2013 ( ARM) IDA
.text:00000000 main
.text:00000000 10 40 2D E9 STMFD SP!, {R4,LR}
.text:00000004 1E 0E 8F E2 ADR R0, aHelloWorld ; "hello, world"
.text:00000008 15 19 00 EB BL __2printf
.text:0000000C 00 00 A0 E3 MOV R0, #0
.text:00000010 10 80 BD E8 LDMFD SP!, {R4,PC}

.text:000001EC 68 65 6C 6C+aHelloWorld DCB "hello, world",0 ; DATA XREF: main+4

, 4 . ,
ARM, Thumb.
, STMFD SP!, {R4,LR}12 , PUSH x86,
(R4 LR) . , armcc
PUSH {r4,lr}. , PUSH Thumb,
, , IDA.
, SP14 , , ,
R4 LR , SP.
, PUSH Thumb,
, . , x86 . , STMFD
PUSH ( ), , SP.
, STMFD .
ADR R0, aHelloWorld PC15 ,
hello, world. PC, ? , - 16
- . , -
PC . ADR ,
. , , .
, ( PC),
-.
BL __2printf17 printf(). :
BL (0xC) LR;
printf(), PC.
printf() , , , ,
, LR.
RISC- ARM CISC18 - x86,
19 .
10 : Apple Xcode 4.6.3 - GCC LLVM
11 , PUSH/ POP, ARM
12 STMFD13
14 stack pointer. SP/ESP/RSP x86/x64. SP ARM.
15 Program Counter. IP/EIP/RIP x86/64. PC ARM.
16 (67.1 (. 704))
17 Branch with Link
18 Complex instruction set computing
19 (5 (. 25))

13
3. HELLO, WORLD! 3. HELLO, WORLD!
, 32- ( ) 32- BL,
24- . ARM 4 (32 )
4, 2 ( ) . 26
, current_P C 32M .
MOV R0, #020 0 R0. - 0, -
R0.
LDMFD SP!, R4,PC21 , STMFD. (
) R4 PC, SP.
POP.
N.B. STMFD R4 LR, LDMFD
R4 PC.
, LR , .
, main() -
printf(). , ,
PC, , , .
main() /++, , -
CRT - .
BX LR .
DCB , ASCII-, DB x86-.

3.4.2. Keil 6/2013 ( Thumb)

Keil Thumb:
armcc.exe thumb c90 O0 1.c

( IDA):

3.12: Keil 6/2013 ( Thumb) + IDA


.text:00000000 main
.text:00000000 10 B5 PUSH {R4,LR}
.text:00000002 C0 A0 ADR R0, aHelloWorld ; "hello, world"
.text:00000004 06 F0 2E F9 BL __2printf
.text:00000008 00 20 MOVS R0, #0
.text:0000000A 10 BD POP {R4,PC}

.text:00000304 68 65 6C 6C+aHelloWorld DCB "hello, world",0 ; DATA XREF: main+2

(16-) , , Thumb.
BL. 16- . 16-
, printf(). 16-
10 , 11 . ,
Thumb- 2 ( 16 ). , Thumb- -
. , . ,
Thumb- BL current_P C 2M .
(PUSH POP) , STMFD/ LDMFD,
SP . ADR , . MOVS 0
R0 .

3.4.3. Xcode 4.6.3 (LLVM) ( ARM)

Xcode 4.6.3 , -
( -O3), .

3.13: Xcode 4.6.3 (LLVM) ( ARM)


__text:000028C4 _hello_world
__text:000028C4 80 40 2D E9 STMFD SP!, {R7,LR}
__text:000028C8 86 06 01 E3 MOV R0, #0x1686
20 MOVe
21 LDMFD22

14
3. HELLO, WORLD! 3. HELLO, WORLD!
__text:000028CC 0D 70 A0 E1 MOV R7, SP
__text:000028D0 00 00 40 E3 MOVT R0, #0
__text:000028D4 00 00 8F E0 ADD R0, PC, R0
__text:000028D8 C3 05 00 EB BL _puts
__text:000028DC 00 00 A0 E3 MOV R0, #0
__text:000028E0 80 80 BD E8 LDMFD SP!, {R7,PC}

__cstring:00003F62 48 65 6C 6C+aHelloWorld_0 DCB "Hello world!",0

STMFD LDMFD .
MOV 0x1686 R0 , Hello world!.
R7 ( , [App10]) frame pointer, .
MOVT R0, #0 (MOVe Top) 0 16 . , MOV
ARM - 16 ,
. , ARM 32 . ,
. ( 16- 31- )
MOVT. , , MOV R0,
#0x1686 . , .
ADD R0, PC, R0 PC R0 Hello world!.
, - , .
BL puts() printf().
printf() puts(). , printf()
puts(). , , printf(),
. 23 .
? puts() 24 .
puts() stdout .
MOV R0, #0, 0 .

3.4.4. Xcode 4.6.3 (LLVM) ( Thumb-2)

Xcode 4.6.3 Thumb-2 :

3.14: Xcode 4.6.3 (LLVM) ( Thumb-2)


__text:00002B6C _hello_world
__text:00002B6C 80 B5 PUSH {R7,LR}
__text:00002B6E 41 F2 D8 30 MOVW R0, #0x13D8
__text:00002B72 6F 46 MOV R7, SP
__text:00002B74 C0 F2 00 00 MOVT.W R0, #0
__text:00002B78 78 44 ADD R0, PC
__text:00002B7A 01 F0 38 EA BLX _puts
__text:00002B7E 00 20 MOVS R0, #0
__text:00002B80 80 BD POP {R7,PC}

...

__cstring:00003E70 48 65 6C 6C 6F 20+aHelloWorld DCB "Hello world!",0xA,0

BL BLX Thumb, , 16- , Thumb-2


, 32- .
Thumb-2 0xFx 0xEx. IDA
. - , ARM : ,
( Thumb Thumb-2 ), , ( ARM) , ,
(.. endianness).
IDA:
ARM ARM64: 4-3-2-1;
Thumb: 2-1;
16- Thumb-2: 2-1-4-3.
23 , puts() \n , .
24 ciselant.de/projects/gcc_printf/gcc_printf.html

15
3. HELLO, WORLD! 3. HELLO, WORLD!
MOVW, MOVT.W BLX 0xFx.
Thumb-2 MOVW R0, #0x13D8 16- R0,
.
MOVT.W R0, #0 , MOVT , Thumb-2.
, BLX BL. ,
LR puts(), Thumb/Thumb-
2 ARM ( ). , , , ( -
ARM):
__symbolstub1:00003FEC _puts ; CODE XREF: _hello_world+E
__symbolstub1:00003FEC 44 F0 9F E5 LDR PC, =__imp__puts

, puts() .
, : puts()
, ?
- .
( DLL Windows, .so *NIX
.dylib Mac OS X). ,
puts().
(Windows PE .exe, ELF Mach-O) , (-
) , .
, ,
.
, __imp__puts 32- ,
. LDR 32- , ,
PC, .
,
, , , .
, , 32-
. , ARM,
, .
( thunk-) Thumb-.
, ( ARM), BL
thunk-, ( X ).

thunk-

Thunk- , , - .
- . , -
, .
Thunk- wrapper-. Wrap , .
:

A piece of coding which provides an address:, according to P. Z. Ingerman, who invented thunks in 1961
as a way of binding actual parameters to their formal denitions in Algol-60 procedure calls. If a procedure is
called with an expression in the place of a formal parameter, the compiler generates a thunk which computes
the expression and leaves the address of the result in some standard location.

Microsoft and IBM have both dened, in their Intel-based systems, a 16-bit environment (with
bletcherous segment registers and 64K address limits) and a 32-bit environment (with at addressing
and semi-real memory management). The two environments can both be running on the same computer
and OS (thanks to what is called, in the Microsoft world, WOW which stands for Windows On Windows). MS
and IBM have both decided that the process of getting from 16- to 32-bit and vice versa is called a thunk;
for Windows 95, there is even a tool THUNK.EXE called a thunk compiler.

( The Jargon File )

16
3. HELLO, WORLD! 3. HELLO, WORLD!
3.4.5. ARM64

GCC

GCC 4.8.1 ARM64:

3.15: GCC 4.8.1 + objdump


1 0000000000400590 <main>:
2 400590: a9bf7bfd stp x29, x30, [sp,#16]!
3 400594: 910003fd mov x29, sp
4 400598: 90000000 adrp x0, 400000 <_init0x3b8>
5 40059c: 91192000 add x0, x0, #0x648
6 4005a0: 97ffffa0 bl 400420 <puts@plt>
7 4005a4: 52800000 mov w0, #0x0 // #0
8 4005a8: a8c17bfd ldp x29, x30, [sp],#16
9 4005ac: d65f03c0 ret
10
11 ...
12
13 Contents of section .rodata:
14 400640 01000200 00000000 48656c6c 6f210a00 ........Hello!..

ARM64 Thumb Thumb-2, ARM, 32- . 2


: B.4.1 (. 976). 64- X-, 32- W-.
STP (Store Pair) : X29 X30. ,
, SP, . ARM64
64-, 8 , 16 .
, SP 16
. pre-index. post-index pre-index
: 28.2 (. 464).
, x86, -
PUSH X29 PUSH X30. X29 ARM64 FP25 , X30 LR,
.
SP X29 ( FP). .
ADRP ADD Hello! X0,
. ARM ,
( 4- . : 28.3.1 (. 465)).
. (ADRP) X0 4-
, (ADD) . : 28.4 (. 466).
0x400000 + 0x648 = 0x400648, , .rodata
- Hello!.
BL puts(). : 3.4.3 (. 15).
MOV 0 W0. W0 32 64- X0:
32 32
X0
W0
X0, main() 0, .
32- ? ARM64, x86-64, int 32-, .
, 32- int, 32 X0.
, , . main()
64- :

3.16: main() uint64_t


#include <stdio.h>
#include <stdint.h>

uint64_t main()
{
printf ("Hello!\n");
25 Frame Pointer

17
3. HELLO, WORLD! 3. HELLO, WORLD!
return 0;
}

, MOV :

3.17: GCC 4.8.1 + objdump


4005a4: d2800000 mov x0, #0x0 // #0

LDP (Load Pair) X29 X30.


. , , SP 16.
post-index.
ARM64 : RET. BX LR, , -
, , ,
.
- GCC .

3.5. MIPS

3.5.1. (global pointer)

(global pointer) MIPS. , -


MIPS 32 , 32- .
( GCC
).
, , register
32768...register + 32767, 16 ). -
- 64KiB .
(global pointer) 64KiB.
printf(),
GCC , , -
. ELF- 64KiB- .sbss (small
BSS26 ) .sdata (small data) .
, ,
.sdata/.sbss.
MS-DOS 94 (. 909)
XMS/EMS, 64KiB.
MIPS. PowerPC .

3.5.2. GCC

, .

3.18: GCC 4.4.5 ( )


1 $LC0:
2 ; \000 :
3 .ascii "Hello, world!\012\000"
4 main:
5 ;
6 ; GP:
7 lui $28,%hi(__gnu_local_gp)
8 addiu $sp,$sp,32
9 addiu $28,$28,%lo(__gnu_local_gp)
10 ; RA :
11 sw $31,28($sp)
12 ; puts() GP $25:
13 lw $25,%call16(puts)($28)
14 ; $4 ($a0):
15 lui $4,%hi($LC0)
26 Block Started by Symbol

18
3. HELLO, WORLD! 3. HELLO, WORLD!
16 ; puts(), link-:
17 jalr $25
18 addiu $4,$4,%lo($LC0) ; branch delay slot
19 ; RA:
20 lw $31,28($sp)
21 ; 0 $zero $v0:
22 move $2,$0
23 ; RA:
24 j $31
25 ; :
26 addiu $sp,$sp,32 ; branch delay slot

, $GP . RA
. puts() printf(). puts() $25 LW
(Load Word). $4 LUI (Load Upper Immediate) ADDIU
(Add Immediate Unsigned Word). LUI 16 (
upper) ADDIU 16 . ADDIU JALR ( branch delay slots?).
$4 $A0, 27 .
JALR (Jump and Link Register) $25 ( puts())
(LW) RA. ARM. : RA
( delay slot ),
( delay slot). JALR RA P C + 8.
LW ADDIU.
LW (Load Word) 19 RA ( ).
MOVE 22 $0 ($ZERO) $2 ($V0). MIPS , -
. , MIPS 0 ,
$0, , 0. : MIPS
, . , MOVE DST, SRC ADD DST, SRC, $ZERO
(DST = SRC + 0), . , MIPS -
. , MOVE. ,
CPU 28 .
J 24 RA, . ADDIU J
J ( branch delay slots?) .
IDA. :

3.19: GCC 4.4.5 (IDA)


1 .text:00000000 main:
2 .text:00000000
3 .text:00000000 var_10 = 0x10
4 .text:00000000 var_4 = 4
5 .text:00000000
6 ;
7 ; GP:
8 .text:00000000 lui $gp, (__gnu_local_gp >> 16)
9 .text:00000004 addiu $sp, 0x20
10 .text:00000008 la $gp, (__gnu_local_gp & 0xFFFF)
11 ; RA :
12 .text:0000000C sw $ra, 0x20+var_4($sp)
13 ; GP :
14 ; - , GCC:
15 .text:00000010 sw $gp, 0x20+var_10($sp)
16 ; puts() GP $t9:
17 .text:00000014 lw $t9, (puts & 0xFFFF)($gp)
18 ; $a0:
19 .text:00000018 lui $a0, ($LC0 >> 16) # "Hello, world!"
20 ; puts(), link-:
21 .text:0000001C jalr $t9
22 .text:00000020 la $a0, ($LC0 & 0xFFFF) # "Hello, world!"
23 ; RA:
24 .text:00000024 lw $ra, 0x20+var_4($sp)
25 ; 0 $zero $v0:
26 .text:00000028 move $v0, $zero
27 ; RA:
27 MIPS C.1 (. 978)
28 -

19
3. HELLO, WORLD! 3. HELLO, WORLD!
28 .text:0000002C jr $ra
29 ; :
30 .text:00000030 addiu $sp, 0x20

15 GP .
GCC, - GCC29 . GP ,
64KiB.
, puts() $T9, T- temporaries
.

3.5.3. GCC

GCC .

3.20: GCC 4.4.5 ( )


1 $LC0:
2 .ascii "Hello, world!\012\000"
3 main:
4 ;
5 ; GP FP :
6 addiu $sp,$sp,32
7 sw $31,28($sp)
8 sw $fp,24($sp)
9 ; FP ( ):
10 move $fp,$sp
11 ; GP:
12 lui $28,%hi(__gnu_local_gp)
13 addiu $28,$28,%lo(__gnu_local_gp)
14 ; :
15 lui $2,%hi($LC0)
16 addiu $4,$2,%lo($LC0)
17 ; puts() GP:
18 lw $2,%call16(puts)($28)
19 nop
20 ; puts():
21 move $25,$2
22 jalr $25
23 nop ; branch delay slot
24
25 ; GP :
26 lw $28,16($fp)
27 ; $2 ($V0) :
28 move $2,$0
29 ; .
30 ; SP:
31 move $sp,$fp
32 ; RA:
33 lw $31,28($sp)
34 ; FP:
35 lw $fp,24($sp)
36 addiu $sp,$sp,32
37 ; RA:
38 j $31
39 nop ; branch delay slot

, FP . 3 NOP30 -.
.
, GCC NOP- (- branch delay slots) ,
, . .
IDA:

3.21: GCC 4.4.5 (IDA)

29 , GCC, .
30 No OPeration

20
3. HELLO, WORLD! 3. HELLO, WORLD!
1 .text:00000000 main:
2 .text:00000000
3 .text:00000000 var_10 = 0x10
4 .text:00000000 var_8 = 8
5 .text:00000000 var_4 = 4
6 .text:00000000
7 ;
8 ; GP FP :
9 .text:00000000 addiu $sp, 0x20
10 .text:00000004 sw $ra, 0x20+var_4($sp)
11 .text:00000008 sw $fp, 0x20+var_8($sp)
12 ; FP ( ):
13 .text:0000000C move $fp, $sp
14 ; GP:
15 .text:00000010 la $gp, __gnu_local_gp
16 .text:00000018 sw $gp, 0x20+var_10($sp)
17 ; :
18 .text:0000001C lui $v0, (aHelloWorld >> 16) # "Hello, world!"
19 .text:00000020 addiu $a0, $v0, (aHelloWorld & 0xFFFF) # "Hello, world!"
20 ; puts() GP:
21 .text:00000024 lw $v0, (puts & 0xFFFF)($gp)
22 .text:00000028 or $at, $zero ; NOP
23 ; puts():
24 .text:0000002C move $t9, $v0
25 .text:00000030 jalr $t9
26 .text:00000034 or $at, $zero ; NOP
27 ; GP :
28 .text:00000038 lw $gp, 0x20+var_10($fp)
29 ; $2 ($V0) :
30 .text:0000003C move $v0, $zero
31 ; .
32 ; SP:
33 .text:00000040 move $sp, $fp
34 ; RA:
35 .text:00000044 lw $ra, 0x20+var_4($sp)
36 ; FP:
37 .text:00000048 lw $fp, 0x20+var_8($sp)
38 .text:0000004C addiu $sp, 0x20
39 ; RA:
40 .text:00000050 jr $ra
41 .text:00000054 or $at, $zero ; NOP

IDA LUI/ADDIU LA (Load Address)


15. , 8 ! ( ),
MIPS, .
: IDA NOP- 22, 26 41. OR $AT, $ZERO. ,
$AT , , , . MIPS,
ISA, NOP-.

3.5.4.

. ? ,
RA GP - ( printf())
. leaf function, . : 2.3
(. 6).

3.5.5. GCC: GDB

3.22: GDB
root@debianmips:~# gcc hw.c O3 o hw
root@debianmips:~# gdb hw
GNU gdb (GDB) 7.0.1debian
Copyright (C) 2009 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.

21
3. HELLO, WORLD! 3. HELLO, WORLD!
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mipslinuxgnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/hw...(no debugging symbols found)...done.
(gdb) b main
Breakpoint 1 at 0x400654
(gdb) run
Starting program: /root/hw

Breakpoint 1, 0x00400654 in main ()


(gdb) set stepmode on
(gdb) disas
Dump of assembler code for function main:
0x00400640 <main+0>: lui gp,0x42
0x00400644 <main+4>: addiu sp,sp,32
0x00400648 <main+8>: addiu gp,gp,30624
0x0040064c <main+12>: sw ra,28(sp)
0x00400650 <main+16>: sw gp,16(sp)
0x00400654 <main+20>: lw t9,32716(gp)
0x00400658 <main+24>: lui a0,0x40
0x0040065c <main+28>: jalr t9
0x00400660 <main+32>: addiu a0,a0,2080
0x00400664 <main+36>: lw ra,28(sp)
0x00400668 <main+40>: move v0,zero
0x0040066c <main+44>: jr ra
0x00400670 <main+48>: addiu sp,sp,32
End of assembler dump.
(gdb) s
0x00400658 in main ()
(gdb) s
0x0040065c in main ()
(gdb) s
0x2ab2de60 in printf () from /lib/libc.so.6
(gdb) x/s $a0
0x400820: "hello, world"
(gdb)

3.6.
x86/ARM x64/ARM64 , 64-. ,
CPU 64-, ,
, , 32- . 64-.

3.7.

3.7.1. #1

main:
push 0xFFFFFFFF
call MessageBeep
xor eax,eax
retn

win32-?
: G.1.1 (. 985).

3.7.2. #2

22
3. HELLO, WORLD! 3. HELLO, WORLD!

main:
pushq %rbp
movq %rsp, %rbp
movl $2, %edi
call sleep
popq %rbp
ret

Linux-? AT&T- .
: G.1.1 (. 985).

23
4. 4.

. - :
push ebp
mov ebp, esp
sub esp, X

: EBP , EBP ESP,


.
EBP ,
. ESP, .
, EBP -
:
mov esp, ebp
pop ebp
ret 0

4.1.
.
: 36.3 (. 490).

24
5. 5.

1 .
+ ESP x86 RSP x64, SP ARM,
- .
PUSH POP ( x86 Thumb- ARM). PUSH -
ESP/ RSP/SP 4 32- ( 8 64-), ,
ESP/ RSP/SP, .
POP (
) 4 ( 8).
- . PUSH -, POP .
, . , .
ARM, , , , -
.

, STMFD/LDMFD, STMED2 /LDMED3 descending- ( ,


). STMFA4 /LDMFA5 , STMEA6 /LDMEA7 ascending-
( , ).

5.1. ?
, , , , ..
.
, , , . ,
: . ,
, .

Heap . Stack

[RT74] :
1 wikipedia.org/wiki/Call_stack
2 Store Multiple Empty Descending ( ARM)
3 Load Multiple Empty Descending ( ARM)
4 Store Multiple Full Ascending ( ARM)
5 Load Multiple Full Ascending ( ARM)
6 Store Multiple Empty Ascending ( ARM)
7 Load Multiple Empty Ascending ( ARM)

25
5. 5.

The user-core part of an image is divided into three logical segments. The program text segment begins
at location 0 in the virtual address space. During execution, this segment is write-protected and a single
copy of it is shared among all processes executing the same program. At the rst 8K byte boundary above
the program text segment in the virtual address space begins a nonshared, writable data segment, the size
of which may be extended by a system call. Starting at the highest address in the virtual address space is a
stack segment, which automatically grows downward as the hardwares stack pointer uctuates.

: -
, , . - ,
.

5.2. ?

5.2.1.

x86

CALL ,
CALL, ( JMP) , .
CALL PUSH address_after_call / JMP.
RET POP tmp /
JMP tmp.
, :
void f()
{
f();
};

MSVC 2008 :
c:\tmp6>cl ss.cpp /Fass.asm
Microsoft (R) 32bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

ss.cpp
c:\tmp6\ss.cpp(4) : warning C4717: 'f' : recursive on all control paths, function will cause runtime
stack overflow

, , :
?f@@YAXXZ PROC ; f
; File c:\tmp6\ss.cpp
; Line 2
push ebp
mov ebp, esp
; Line 3
call ?f@@YAXXZ ; f
; Line 4
pop ebp
ret 0
?f@@YAXXZ ENDP ; f

, (/Ox), , ,
8 :
?f@@YAXXZ PROC ; f
; File c:\tmp6\ss.cpp
; Line 2
$LL3@f:
; Line 3
jmp SHORT $LL3@f
8

26
5. 5.
?f@@YAXXZ ENDP ; f

GCC 4.4.1 , .

ARM

ARM RA, , . -
Hello, world! (3.4 (. 12)), RA LR (link register).
- LR , .
, PUSH R4-R7,LR , POP R4-R7,PC
, , LR.
, , RISC leaf
function9 . , leaf- LR ( ).
, , . , ARM
leaf- . x86,
10 . , ,
.
: 8.3.2 (. 97), 8.3.3 (. 97), 19.17 (. 326), 19.33 (. 343), 19.5.4 (. 344), 15.4
(. 205), 15.2 (. 204), 17.3 (. 225).

5.2.2.

x86 cdecl:
push arg3
push arg2
push arg1
call f
add esp, 12 ; 4*3=12

.
, f():
ESP
ESP+4 #1, IDA arg_0
ESP+8 #2, IDA arg_4
ESP+0xC #3, IDA arg_8

. (64 (. 689)). ,
, , ,
. , .
, ,
EAX. 11 . , x86 ARM -
.

, .
( printf()) (
%). -
printf("%d %d %d", 1234);

printf() 1234, , .

, main() : main(), main(int argc, char *argv[]) -


main(int argc, char *argv[], char *envp[]).
, CRT- main() :
9 infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka13785.html
10 -, , PDP-11 VAX CALL ( ) 50% ( -
), , - [Ray03, Chapter 4, Part II].
11 , , 1.4.1 [Knu98, 1.4.1],

JMP, .
, IBM System/360.

27
5. 5.

push envp
push argv
push argc
call main
...

main() , , , , .
main() main(int argc, char *argv[]), ,
. , main(int argc), .

5.2.3.

,
. .
. -
. .

5.2.4. x86: alloca()

alloca()12 .
malloc(), .
free() , (4 (. 24)) ESP
.
alloca().
, , ESP , ESP
. :
#ifdef __GNUC__
#include <alloca.h> // GCC
#else
#include <malloc.h> // MSVC
#endif
#include <stdio.h>

void f()
{
char *buf=(char*)alloca (600);
#ifdef __GNUC__
snprintf (buf, 600, "hi! %d, %d, %d\n", 1, 2, 3); // GCC
#else
_snprintf (buf, 600, "hi! %d, %d, %d\n", 1, 2, 3); // MSVC
#endif

puts (buf);
};

_snprintf() , printf(), stdout (..


), buf. puts() buf stdout. ,
printf(),
.

MSVC

(MSVC 2010):

5.1: MSVC 2010


...

12 MSVC, alloca16.asm chkstk.asm C:\Program Files (x86)\Microsoft Visual


Studio 10.0\VC\crt\src\intel

28
5. 5.
mov eax, 600 ; 00000258H
call __alloca_probe_16
mov esi, esp

push 3
push 2
push 1
push OFFSET $SG2672
push 600 ; 00000258H
push esi
call __snprintf

push esi
call _puts
add esp, 28 ; 0000001cH

...

alloca() EAX, 13 . alloca() ESP


600 , buf.

GCC + Intel

GCC 4.4.1 :

5.2: GCC 4.7.3


.LC0:
.string "hi! %d, %d, %d\n"
f:
push ebp
mov ebp, esp
push ebx
sub esp, 660
lea ebx, [esp+39]
and ebx, 16 ; 16-
mov DWORD PTR [esp], ebx ; s
mov DWORD PTR [esp+20], 3
mov DWORD PTR [esp+16], 2
mov DWORD PTR [esp+12], 1
mov DWORD PTR [esp+8], OFFSET FLAT:.LC0 ; "hi! %d, %d, %d\n"
mov DWORD PTR [esp+4], 600 ; maxlen
call _snprintf
mov DWORD PTR [esp], ebx ; s
call puts
mov ebx, DWORD PTR [ebp4]
leave
ret

GCC + AT&T

, AT&T:

5.3: GCC 4.7.3


.LC0:
.string "hi! %d, %d, %d\n"
f:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $660, %esp
leal 39(%esp), %ebx
andl $16, %ebx
13 , alloca() , .. compiler intrinsic(90 (. 898)) .
, , , alloca() MSVC14
, , VM15 .

29
5. 5.
movl %ebx, (%esp)
movl $3, 20(%esp)
movl $2, 16(%esp)
movl $1, 12(%esp)
movl $.LC0, 8(%esp)
movl $600, 4(%esp)
call _snprintf
movl %ebx, (%esp)
call puts
movl 4(%ebp), %ebx
leave
ret

, .
, movl $3, 20(%esp) mov DWORD PTR [esp+20], 3 Intel.
+ AT&T (%).

5.2.5. (Windows) SEH

SEH16 ( ).
: (68.3 (. 718)).

5.2.6.

(18.2 (. 274)).

5.2.7.

, SEH- , ,
, (
ADD). , , .
(heap) .

5.3.
32- :

ESP-0xC #2, IDA var_8
ESP-8 #1, IDA var_4
ESP-4 EBP
ESP
ESP+4 #1, IDA arg_0
ESP+8 #2, IDA arg_4
ESP+0xC #3, IDA arg_8

5.4.
. ? ,
. :
#include <stdio.h>

void f1()
{
int a=1, b=2, c=3;
};
16 Structured Exception Handling : 68.3 (. 718)

30
5. 5.

void f2()
{
int a, b, c;
printf ("%d, %d, %d\n", a, b, c);
};

int main()
{
f1();
f2();
};

5.4: MSVC 2010


$SG2752 DB '%d, %d, %d', 0aH, 00H

_c$ = 12 ; size = 4
_b$ = 8 ; size = 4
_a$ = 4 ; size = 4
_f1 PROC
push ebp
mov ebp, esp
sub esp, 12
mov DWORD PTR _a$[ebp], 1
mov DWORD PTR _b$[ebp], 2
mov DWORD PTR _c$[ebp], 3
mov esp, ebp
pop ebp
ret 0
_f1 ENDP

_c$ = 12 ; size = 4
_b$ = 8 ; size = 4
_a$ = 4 ; size = 4
_f2 PROC
push ebp
mov ebp, esp
sub esp, 12
mov eax, DWORD PTR _c$[ebp]
push eax
mov ecx, DWORD PTR _b$[ebp]
push ecx
mov edx, DWORD PTR _a$[ebp]
push edx
push OFFSET $SG2752 ; '%d, %d, %d'
call DWORD PTR __imp__printf
add esp, 16
mov esp, ebp
pop ebp
ret 0
_f2 ENDP

_main PROC
push ebp
mov ebp, esp
call _f1
call _f2
xor eax, eax
pop ebp
ret 0
_main ENDP


c:\Polygon\c>cl st.c /Fast.asm /MD
Microsoft (R) 32bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

31
5. 5.
st.c
c:\polygon\c\st.c(11) : warning C4700: uninitialized local variable 'c' used
c:\polygon\c\st.c(11) : warning C4700: uninitialized local variable 'b' used
c:\polygon\c\st.c(11) : warning C4700: uninitialized local variable 'a' used
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:st.exe
st.obj


c:\Polygon\c>st
1, 2, 3

. . f2(). ,
.

32
5. 5.
OllyDbg:

. 5.1: OllyDbg: f1()

f1() a, b c 0x14F860 ..

33
5. 5.
f2():

. 5.2: OllyDbg: f2()

... a, b c f2() ! ,
.
SP -
, .. ).
.
, ( ) .
, , .
? ,
( ) .

5.5.

5.5.1. #1

MSVC , . ? -
MSVC (/Ox)? GCC ?
#include <stdio.h>

int main()
{
printf ("%d, %d, %d\n");

return 0;
};

: G.1.2 (. 985).

5.5.2. #2

5.5: MSVC 2010


$SG3103 DB '%d', 0aH, 00H

34
5. 5.

_main PROC
push 0
call DWORD PTR __imp___time64
push edx
push eax
push OFFSET $SG3103 ; '%d'
call DWORD PTR __imp__printf
add esp, 16
xor eax, eax
ret 0
_main ENDP

5.6: Keil 6/2013 ( ARM)


main PROC
PUSH {r4,lr}
MOV r0,#0
BL time
MOV r1,r0
ADR r0,|L0.32|
BL __2printf
MOV r0,#0
POP {r4,pc}
ENDP

|L0.32|
DCB "%d\n",0

5.7: Keil 6/2013 ( Thumb)


main PROC
PUSH {r4,lr}
MOVS r0,#0
BL time
MOVS r1,r0
ADR r0,|L0.20|
BL __2printf
MOVS r0,#0
POP {r4,pc}
ENDP

|L0.20|
DCB "%d\n",0

5.8: GCC 4.9 (ARM64)


main:
stp x29, x30, [sp, 16]!
mov x0, 0
add x29, sp, 0
bl time
mov x1, x0
ldp x29, x30, [sp], 16
adrp x0, .LC0
add x0, x0, :lo12:.LC0
b printf
.LC0:
.string "%d\n"

5.9: GCC 4.4.5 (MIPS) (IDA)


main:

var_10 = 0x10
var_4 = 4

lui $gp, (__gnu_local_gp >> 16)


addiu $sp, 0x20
la $gp, (__gnu_local_gp & 0xFFFF)

35
5. 5.
sw $ra, 0x20+var_4($sp)
sw $gp, 0x20+var_10($sp)
lw $t9, (time & 0xFFFF)($gp)
or $at, $zero
jalr $t9
move $a0, $zero
lw $gp, 0x20+var_10($sp)
lui $a0, ($LC0 >> 16) # "%d\n"
lw $t9, (printf & 0xFFFF)($gp)
lw $ra, 0x20+var_4($sp)
la $a0, ($LC0 & 0xFFFF) # "%d\n"
move $a1, $v0
jr $t9
addiu $sp, 0x20

$LC0: .ascii "%d\n"<0> # DATA XREF: main+28

: G.1.2 (. 985).

36
6. PRINTF() 6. PRINTF()

printf()

Hello, world! (3 (. 7)), main():


#include <stdio.h>

int main()
{
printf("a=%d; b=%d; c=%d", 1, 2, 3);
return 0;
};

6.1. x86

6.1.1. x86: 3

MSVC

MSVC 2010 Express, :


$SG3830 DB 'a=%d; b=%d; c=%d', 00H

...

push 3
push 2
push 1
push OFFSET $SG3830
call _printf
add esp, 16 ; 00000010H

, , , printf()
: .
, , int 32- , , 32 , 4 .
, 4 . 4 4 = 16 16 3
int.
ADD ESP, X ESP - ,
, , X 4.
, cdecl- , 32- .
. (64 (. 689)).
, , ,
:
push a1
push a2
call ...
...
push a1

37
6. PRINTF() 6. PRINTF()
call ...
...
push a1
push a2
push a3
call ...
add esp, 24

6.1: x86
.text:100113E7 push 3
.text:100113E9 call sub_100018B0 ; (3)
.text:100113EE call sub_100019D0 ;
.text:100113F3 call sub_10006A90 ;
.text:100113F8 push 1
.text:100113FA call sub_100018B0 ; (1)
.text:100113FF add esp, 8 ;

38
6. PRINTF() 6. PRINTF()
MSVC OllyDbg

OllyDbg. win32- .
MSVC 2012 /MD MSVCR*.DLL,
.
OllyDbg. ntdll.dll, F9 ().
CRT-. main().
, (MSVC main()
):

. 6.1: OllyDbg: main()

PUSH EBP, F2 ( ) F9 (). -


, CRT-, .

39
6. PRINTF() 6. PRINTF()
F8 ( , ) 6 , .. 6 :

. 6.2: OllyDbg: printf()

PC CALL printf. OllyDbg, , -


, . F8, EIP
. ESP , .

? :

. 6.3: OllyDbg: ( )

3 : , OllyDbg. OllyDbg
printf()-, 3 .
, Follow in dump
, - . .
, .
, , .

40
6. PRINTF() 6. PRINTF()
F8 ( , ).
:

. 6.4: printf()

. 6.5: OllyDbg printf()

EAX 0xD (13). : printf() .


EIP . , CALL printf. ECX EDX
. , printf() - .
, ESP . - !
3 , . , cdecl,
ESP . .

41
6. PRINTF() 6. PRINTF()
F8 , ADD ESP, 10:

. 6.6: OllyDbg: ADD ESP, 10

ESP , ! , -
. (SP) .
, , .

GCC

Linux GCC 4.4.1 IDA:


main proc near

var_10 = dword ptr 10h


var_C = dword ptr 0Ch
var_8 = dword ptr 8
var_4 = dword ptr 4

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 10h
mov eax, offset aADBDCD ; "a=%d; b=%d; c=%d"
mov [esp+10h+var_4], 3
mov [esp+10h+var_8], 2
mov [esp+10h+var_C], 1
mov [esp+10h+var_10], eax
call _printf
mov eax, 0
leave
retn
main endp

, GCC, MSVC
. GCC PUSH/ POP.

GCC GDB

GDB1 Linux.
-g .
$ gcc 1.c g o 1

1 GNU debugger

42
6. PRINTF() 6. PRINTF()

$ gdb 1
GNU gdb (GDB) 7.6.1ubuntu
Copyright (C) 2013 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 "i686linuxgnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dennis/polygon/1...done.

6.2: printf()
(gdb) b printf
Breakpoint 1 at 0x80482f0

. printf(), GDB .
(gdb) run
Starting program: /home/dennis/polygon/1

Breakpoint 1, __printf (format=0x80484f0 "a=%d; b=%d; c=%d") at printf.c:29


29 printf.c: No such file or directory.

10 . .
(gdb) x/10w $esp
0xbffff11c: 0x0804844a 0x080484f0 0x00000001 0x00000002
0xbffff12c: 0x00000003 0x08048460 0x00000000 0x00000000
0xbffff13c: 0xb7e29905 0x00000001

RA (0x0804844a). , :
(gdb) x/5i 0x0804844a
0x804844a <main+45>: mov $0x0,%eax
0x804844f <main+50>: leave
0x8048450 <main+51>: ret
0x8048451: xchg %ax,%ax
0x8048453: xchg %ax,%ax

XCHG , NOP.
(0x080484f0) :
(gdb) x/s 0x080484f0
0x80484f0: "a=%d; b=%d; c=%d"

3 (1, 2, 3) printf(). ,
, , .. .
nish. . -
printf().
(gdb) finish
Run till exit from #0 __printf (format=0x80484f0 "a=%d; b=%d; c=%d") at printf.c:29
main () at 1.c:6
6 return 0;
Value returned is $2 = 13

GDB , printf() EAX (13). , OllyDbg,


.
return 0; 1.c 6. , 1.c
GDB . GDB , - ? -
, ,
. GDB - .
. 13 EAX:

43
6. PRINTF() 6. PRINTF()

(gdb) info registers


eax 0xd 13
ecx 0x0 0
edx 0x0 0
ebx 0xb7fc0000 1208221696
esp 0xbffff120 0xbffff120
ebp 0xbffff138 0xbffff138
esi 0x0 0
edi 0x0 0
eip 0x804844a 0x804844a <main+45>
...

. , -
.
(gdb) disas
Dump of assembler code for function main:
0x0804841d <+0>: push %ebp
0x0804841e <+1>: mov %esp,%ebp
0x08048420 <+3>: and $0xfffffff0,%esp
0x08048423 <+6>: sub $0x10,%esp
0x08048426 <+9>: movl $0x3,0xc(%esp)
0x0804842e <+17>: movl $0x2,0x8(%esp)
0x08048436 <+25>: movl $0x1,0x4(%esp)
0x0804843e <+33>: movl $0x80484f0,(%esp)
0x08048445 <+40>: call 0x80482f0 <printf@plt>
=> 0x0804844a <+45>: mov $0x0,%eax
0x0804844f <+50>: leave
0x08048450 <+51>: ret
End of assembler dump.

GDB AT&T. -
Intel:
(gdb) set disassemblyflavor intel
(gdb) disas
Dump of assembler code for function main:
0x0804841d <+0>: push ebp
0x0804841e <+1>: mov ebp,esp
0x08048420 <+3>: and esp,0xfffffff0
0x08048423 <+6>: sub esp,0x10
0x08048426 <+9>: mov DWORD PTR [esp+0xc],0x3
0x0804842e <+17>: mov DWORD PTR [esp+0x8],0x2
0x08048436 <+25>: mov DWORD PTR [esp+0x4],0x1
0x0804843e <+33>: mov DWORD PTR [esp],0x80484f0
0x08048445 <+40>: call 0x80482f0 <printf@plt>
=> 0x0804844a <+45>: mov eax,0x0
0x0804844f <+50>: leave
0x08048450 <+51>: ret
End of assembler dump.

. GDB , , .
(gdb) step
7 };

MOV EAX, 0. EAX .


(gdb) info registers
eax 0x0 0
ecx 0x0 0
edx 0x0 0
ebx 0xb7fc0000 1208221696
esp 0xbffff120 0xbffff120
ebp 0xbffff138 0xbffff138
esi 0x0 0
edi 0x0 0
eip 0x804844f 0x804844f <main+50>
...

44
6. PRINTF() 6. PRINTF()
6.1.2. x64: 8

, , ,
9 ( printf() 8 int):
#include <stdio.h>

int main()
{
printf("a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n", 1, 2, 3, 4, 5, 6, 7, 8);
return 0;
};

MSVC

, 4 Win64 RCX, RDX, R8, R9 ,


. . , PUSH , MOV
.

6.3: MSVC 2012 x64


$SG2923 DB 'a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d', 0aH, 00H

main PROC
sub rsp, 88

mov DWORD PTR [rsp+64], 8


mov DWORD PTR [rsp+56], 7
mov DWORD PTR [rsp+48], 6
mov DWORD PTR [rsp+40], 5
mov DWORD PTR [rsp+32], 4
mov r9d, 3
mov r8d, 2
mov edx, 1
lea rcx, OFFSET FLAT:$SG2923
call printf

; 0
xor eax, eax

add rsp, 88
ret 0
main ENDP
_TEXT ENDS
END

, int 8 , 4? ,
: 64-, 8 . :
. ,
. 32- : 4 .

GCC

*NIX- x86-64 , 6 RDI, RSI, RDX, RCX,


R8, R9. . GCC , EDI RDI
: 3.2.2 (. 11).
printf() EAX : 3.2.2 (. 11).

6.4: GCC 4.4.6 x64


.LC0:
.string "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n"

main:
sub rsp, 40

mov r9d, 5

45
6. PRINTF() 6. PRINTF()
mov r8d, 4
mov ecx, 3
mov edx, 2
mov esi, 1
mov edi, OFFSET FLAT:.LC0
xor eax, eax ;
mov DWORD PTR [rsp+16], 8
mov DWORD PTR [rsp+8], 7
mov DWORD PTR [rsp], 6
call printf

; 0

xor eax, eax


add rsp, 40
ret

GCC + GDB

GDB.
$ gcc g 2.c o 2

$ gdb 2
GNU gdb (GDB) 7.6.1ubuntu
Copyright (C) 2013 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_64linuxgnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dennis/polygon/2...done.

6.5: printf(),
(gdb) b printf
Breakpoint 1 at 0x400410
(gdb) run
Starting program: /home/dennis/polygon/2

Breakpoint 1, __printf (format=0x400628 "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n") at printf.
c:29
29 printf.c: No such file or directory.

RSI/ RDX/ RCX/ R8/ R9 . RIP printf().


(gdb) info registers
rax 0x0 0
rbx 0x0 0
rcx 0x3 3
rdx 0x2 2
rsi 0x1 1
rdi 0x400628 4195880
rbp 0x7fffffffdf60 0x7fffffffdf60
rsp 0x7fffffffdf38 0x7fffffffdf38
r8 0x4 4
r9 0x5 5
r10 0x7fffffffdce0 140737488346336
r11 0x7ffff7a65f60 140737348263776
r12 0x400440 4195392
r13 0x7fffffffe040 140737488347200
r14 0x0 0
r15 0x0 0
rip 0x7ffff7a65f60 0x7ffff7a65f60 <__printf>
...

46
6. PRINTF() 6. PRINTF()
6.6:
(gdb) x/s $rdi
0x400628: "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n"

x/g g giant words, .. 64- .


(gdb) x/10g $rsp
0x7fffffffdf38: 0x0000000000400576 0x0000000000000006
0x7fffffffdf48: 0x0000000000000007 0x00007fff00000008
0x7fffffffdf58: 0x0000000000000000 0x0000000000000000
0x7fffffffdf68: 0x00007ffff7a33de5 0x0000000000000000
0x7fffffffdf78: 0x00007fffffffe048 0x0000000100000000

, , RA. 3 : 6, 7, 8. , 8
32- : 0x00007fff00000008. ,
int, 32-. .
GDB main(), , printf():
(gdb) set disassemblyflavor intel
(gdb) disas 0x0000000000400576
Dump of assembler code for function main:
0x000000000040052d <+0>: push rbp
0x000000000040052e <+1>: mov rbp,rsp
0x0000000000400531 <+4>: sub rsp,0x20
0x0000000000400535 <+8>: mov DWORD PTR [rsp+0x10],0x8
0x000000000040053d <+16>: mov DWORD PTR [rsp+0x8],0x7
0x0000000000400545 <+24>: mov DWORD PTR [rsp],0x6
0x000000000040054c <+31>: mov r9d,0x5
0x0000000000400552 <+37>: mov r8d,0x4
0x0000000000400558 <+43>: mov ecx,0x3
0x000000000040055d <+48>: mov edx,0x2
0x0000000000400562 <+53>: mov esi,0x1
0x0000000000400567 <+58>: mov edi,0x400628
0x000000000040056c <+63>: mov eax,0x0
0x0000000000400571 <+68>: call 0x400410 <printf@plt>
0x0000000000400576 <+73>: mov eax,0x0
0x000000000040057b <+78>: leave
0x000000000040057c <+79>: ret
End of assembler dump.

printf(), EAX, EAX -


. RIP LEAVE, .. main() .
(gdb) finish
Run till exit from #0 __printf (format=0x400628 "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n")
at printf.c:29
a=1; b=2; c=3; d=4; e=5; f=6; g=7; h=8
main () at 2.c:6
6 return 0;
Value returned is $1 = 39
(gdb) next
7 };
(gdb) info registers
rax 0x0 0
rbx 0x0 0
rcx 0x26 38
rdx 0x7ffff7dd59f0 140737351866864
rsi 0x7fffffd9 2147483609
rdi 0x0 0
rbp 0x7fffffffdf60 0x7fffffffdf60
rsp 0x7fffffffdf40 0x7fffffffdf40
r8 0x7ffff7dd26a0 140737351853728
r9 0x7ffff7a60134 140737348239668
r10 0x7fffffffd5b0 140737488344496
r11 0x7ffff7a95900 140737348458752
r12 0x400440 4195392
r13 0x7fffffffe040 140737488347200
r14 0x0 0
r15 0x0 0

47
6. PRINTF() 6. PRINTF()
rip 0x40057b 0x40057b <main+78>
...

6.2. ARM

6.2.1. ARM: 3

ARM : 4 R0-R3;
. , fastcall (64.3 (. 690)) win64 (64.5.1
(. 691)).

32- ARM

Keil 6/2013 ( ARM)

6.7: Keil 6/2013 ( ARM)


.text:00000000 main
.text:00000000 10 40 2D E9 STMFD SP!, {R4,LR}
.text:00000004 03 30 A0 E3 MOV R3, #3
.text:00000008 02 20 A0 E3 MOV R2, #2
.text:0000000C 01 10 A0 E3 MOV R1, #1
.text:00000010 08 00 8F E2 ADR R0, aADBDCD ; "a=%d; b=%d; c=%d"
.text:00000014 06 00 00 EB BL __2printf
.text:00000018 00 00 A0 E3 MOV R0, #0 ; return 0
.text:0000001C 10 80 BD E8 LDMFD SP!, {R4,PC}

, 4 R0-R3, : - printf()
R0, 1 R1, 2 R2 3 R3.
0x18 0 R0 return 0.
.
Keil 6/2013 .

Keil 6/2013 ( Thumb)

6.8: Keil 6/2013 ( Thumb)


.text:00000000 main
.text:00000000 10 B5 PUSH {R4,LR}
.text:00000002 03 23 MOVS R3, #3
.text:00000004 02 22 MOVS R2, #2
.text:00000006 01 21 MOVS R1, #1
.text:00000008 02 A0 ADR R0, aADBDCD ; "a=%d; b=%d; c=%d"
.text:0000000A 00 F0 0D F8 BL __2printf
.text:0000000E 00 20 MOVS R0, #0
.text:00000010 10 BD POP {R4,PC}

ARM.

Keil 6/2013 ( ARM) + return

, return 0:
#include <stdio.h>

void main()
{
printf("a=%d; b=%d; c=%d", 1, 2, 3);
};

48
6. PRINTF() 6. PRINTF()
:

6.9: Keil 6/2013 ( ARM)


.text:00000014 main
.text:00000014 03 30 A0 E3 MOV R3, #3
.text:00000018 02 20 A0 E3 MOV R2, #2
.text:0000001C 01 10 A0 E3 MOV R1, #1
.text:00000020 1E 0E 8F E2 ADR R0, aADBDCD ; "a=%d; b=%d; c=%d\n"
.text:00000024 CB 18 00 EA B __2printf

(-O3) ARM, B
BL. , ,
, (, R0 LR). B
, LR, JMP x86.
? . : 1) ,
SP; 2) printf() , . printf(),
, , LR. LR ,
! , printf() .
LR, LR. LR, ,
printf(), , !
.
, .
: 13.1.1 (. 149).

ARM64

GCC (Linaro) 4.9

6.10: GCC (Linaro) 4.9


.LC1:
.string "a=%d; b=%d; c=%d"
f2:
; FP LR :
stp x29, x30, [sp, 16]!
; (FP=SP):
add x29, sp, 0
adrp x0, .LC1
add x0, x0, :lo12:.LC1
mov w1, 1
mov w2, 2
mov w3, 3
bl printf
mov w0, 0
; FP LR
ldp x29, x30, [sp], 16
ret

, STP (Store Pair) FP (X29) LR (X30) . ADD X29, SP, 0


. SP X29.
ADRP/ ADD . lo12 12 , ..,
12 LC1 ADD.
%d printf() 32- int, 1, 2 3 32- .
GCC (Linaro) 4.9 .

6.2.2. ARM: 8

9- : 6.1.2 (. 45).
#include <stdio.h>

int main()
{

49
6. PRINTF() 6. PRINTF()
printf("a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n", 1, 2, 3, 4, 5, 6, 7, 8);
return 0;
};

Keil 6/2013: ARM

.text:00000028 main
.text:00000028
.text:00000028 var_18 = 0x18
.text:00000028 var_14 = 0x14
.text:00000028 var_4 = 4
.text:00000028
.text:00000028 04 E0 2D E5 STR LR, [SP,#var_4]!
.text:0000002C 14 D0 4D E2 SUB SP, SP, #0x14
.text:00000030 08 30 A0 E3 MOV R3, #8
.text:00000034 07 20 A0 E3 MOV R2, #7
.text:00000038 06 10 A0 E3 MOV R1, #6
.text:0000003C 05 00 A0 E3 MOV R0, #5
.text:00000040 04 C0 8D E2 ADD R12, SP, #0x18+var_14
.text:00000044 0F 00 8C E8 STMIA R12, {R0R3}
.text:00000048 04 00 A0 E3 MOV R0, #4
.text:0000004C 00 00 8D E5 STR R0, [SP,#0x18+var_18]
.text:00000050 03 30 A0 E3 MOV R3, #3
.text:00000054 02 20 A0 E3 MOV R2, #2
.text:00000058 01 10 A0 E3 MOV R1, #1
.text:0000005C 6E 0F 8F E2 ADR R0, aADBDCDDDEDFDGD ; "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%"...
.text:00000060 BC 18 00 EB BL __2printf
.text:00000064 14 D0 8D E2 ADD SP, SP, #0x14
.text:00000068 04 F0 9D E4 LDR PC, [SP+4+var_4],#4

:
:
STR LR, [SP,#var_4]! LR, -
printf(). pre-index. , SP
4, SP LR. x86 -
PUSH. : 28.2 (. 464).
SUB SP, SP, #0x14 SP, , ,
0x14 (20) . , 5 32-
printf(). 4 , 5 4 = 20. 4 32-
.
5, 6, 7 8 : R0, R1, R2 R3 . ADD
R12, SP, #0x18+var_14 R12 , 4 .
var_14 , -0x14. IDA, ,
. var_?, IDA, R12
SP+4. STMIA R12, R0-R3 R0-R3
, R12. STMIA Store Multiple Increment After. Increment
After , R12 4 .
4 : 4 R0, STR R0, [SP,#0x18+var_18]
. var_18 -0x18, 0, R0 (4) , SP.
1, 2 3 :
(a, b, c) (1, 2, 3 ) R1, R2 R3
printf(), 5 , :
printf().
:
ADD SP, SP, #0x14 SP , , -
. , , ,
.
LDR PC, [SP+4+var_4],#4 PC LR ,
. , PC ,
SP (4 + var_4 = 4 + (4) = 0, LDR PC, [SP],#4),

50
6. PRINTF() 6. PRINTF()
SP 4. post-index2 . IDA ?
, var_4
LR. - POP PC x863 .

Keil 6/2013: Thumb

.text:0000001C printf_main2
.text:0000001C
.text:0000001C var_18 = 0x18
.text:0000001C var_14 = 0x14
.text:0000001C var_8 = 8
.text:0000001C
.text:0000001C 00 B5 PUSH {LR}
.text:0000001E 08 23 MOVS R3, #8
.text:00000020 85 B0 SUB SP, SP, #0x14
.text:00000022 04 93 STR R3, [SP,#0x18+var_8]
.text:00000024 07 22 MOVS R2, #7
.text:00000026 06 21 MOVS R1, #6
.text:00000028 05 20 MOVS R0, #5
.text:0000002A 01 AB ADD R3, SP, #0x18+var_14
.text:0000002C 07 C3 STMIA R3!, {R0R2}
.text:0000002E 04 20 MOVS R0, #4
.text:00000030 00 90 STR R0, [SP,#0x18+var_18]
.text:00000032 03 23 MOVS R3, #3
.text:00000034 02 22 MOVS R2, #2
.text:00000036 01 21 MOVS R1, #1
.text:00000038 A0 A0 ADR R0, aADBDCDDDEDFDGD ; "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%"...
.text:0000003A 06 F0 D9 F8 BL __2printf
.text:0000003E
.text:0000003E loc_3E ; CODE XREF: example13_f+16
.text:0000003E 05 B0 ADD SP, SP, #0x14
.text:00000040 00 BD POP {PC}

, Thumb
: 8 , 5, 6, 7 4 .

Xcode 4.6.3 (LLVM): ARM

__text:0000290C _printf_main2
__text:0000290C
__text:0000290C var_1C = 0x1C
__text:0000290C var_C = 0xC
__text:0000290C
__text:0000290C 80 40 2D E9 STMFD SP!, {R7,LR}
__text:00002910 0D 70 A0 E1 MOV R7, SP
__text:00002914 14 D0 4D E2 SUB SP, SP, #0x14
__text:00002918 70 05 01 E3 MOV R0, #0x1570
__text:0000291C 07 C0 A0 E3 MOV R12, #7
__text:00002920 00 00 40 E3 MOVT R0, #0
__text:00002924 04 20 A0 E3 MOV R2, #4
__text:00002928 00 00 8F E0 ADD R0, PC, R0
__text:0000292C 06 30 A0 E3 MOV R3, #6
__text:00002930 05 10 A0 E3 MOV R1, #5
__text:00002934 00 20 8D E5 STR R2, [SP,#0x1C+var_1C]
__text:00002938 0A 10 8D E9 STMFA SP, {R1,R3,R12}
__text:0000293C 08 90 A0 E3 MOV R9, #8
__text:00002940 01 10 A0 E3 MOV R1, #1
__text:00002944 02 20 A0 E3 MOV R2, #2
__text:00002948 03 30 A0 E3 MOV R3, #3
__text:0000294C 10 90 8D E5 STR R9, [SP,#0x1C+var_C]
__text:00002950 A4 05 00 EB BL _printf
__text:00002954 07 D0 A0 E1 MOV SP, R7
__text:00002958 80 80 BD E8 LDMFD SP!, {R7,PC}

2 : 28.2 (. 464).
3 x86 IP/EIP/RIP POP, , .

51
6. PRINTF() 6. PRINTF()
, , , STMFA (Store Multiple Full Ascending)
STMIB (Store Multiple Increment Before). SP
, .
, . , R0
, 0x2918, 0x2920 0x2928, .
, ,
.
. , MOVT R0, #0 ADD R0, PC, R0 ,
R0. MOVT R0, #0 MOV R2, #4 -
, . ,
, .

Xcode 4.6.3 (LLVM): Thumb-2

__text:00002BA0 _printf_main2
__text:00002BA0
__text:00002BA0 var_1C = 0x1C
__text:00002BA0 var_18 = 0x18
__text:00002BA0 var_C = 0xC
__text:00002BA0
__text:00002BA0 80 B5 PUSH {R7,LR}
__text:00002BA2 6F 46 MOV R7, SP
__text:00002BA4 85 B0 SUB SP, SP, #0x14
__text:00002BA6 41 F2 D8 20 MOVW R0, #0x12D8
__text:00002BAA 4F F0 07 0C MOV.W R12, #7
__text:00002BAE C0 F2 00 00 MOVT.W R0, #0
__text:00002BB2 04 22 MOVS R2, #4
__text:00002BB4 78 44 ADD R0, PC ; char *
__text:00002BB6 06 23 MOVS R3, #6
__text:00002BB8 05 21 MOVS R1, #5
__text:00002BBA 0D F1 04 0E ADD.W LR, SP, #0x1C+var_18
__text:00002BBE 00 92 STR R2, [SP,#0x1C+var_1C]
__text:00002BC0 4F F0 08 09 MOV.W R9, #8
__text:00002BC4 8E E8 0A 10 STMIA.W LR, {R1,R3,R12}
__text:00002BC8 01 21 MOVS R1, #1
__text:00002BCA 02 22 MOVS R2, #2
__text:00002BCC 03 23 MOVS R3, #3
__text:00002BCE CD F8 10 90 STR.W R9, [SP,#0x1C+var_C]
__text:00002BD2 01 F0 0A EA BLX _printf
__text:00002BD6 05 B0 ADD SP, SP, #0x14
__text:00002BD8 80 BD POP {R7,PC}

, , , Thumb-.

ARM64

GCC (Linaro) 4.9

6.11: GCC (Linaro) 4.9


.LC2:
.string "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n"
f3:
; :
sub sp, sp, #32
; FP LR :
stp x29, x30, [sp,16]
; (FP=SP):
add x29, sp, 16
adrp x0, .LC2 ; "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n"
add x0, x0, :lo12:.LC2
mov w1, 8 ; 9th argument
str w1, [sp] ; store 9th argument in the stack
mov w1, 1
mov w2, 2

52
6. PRINTF() 6. PRINTF()
mov w3, 3
mov w4, 4
mov w5, 5
mov w6, 6
mov w7, 7
bl printf
sub sp, x29, #16
; FP LR
ldp x29, x30, [sp,16]
add sp, sp, 32
ret

8 X- W-: [ARM13c]. 64- ,


X0. 32- int, 32-
(W-). (8) . ,
, .
GCC (Linaro) 4.9 .

6.3. MIPS

6.3.1. 3

GCC 4.4.5

Hello, world! , printf() puts()


$5$7 ( $A0$A2).
A-. , .

6.12: GCC 4.4.5 ( )


$LC0:
.ascii "a=%d; b=%d; c=%d\000"
main:
; :
lui $28,%hi(__gnu_local_gp)
addiu $sp,$sp,32
addiu $28,$28,%lo(__gnu_local_gp)
sw $31,28($sp)
; printf():
lw $25,%call16(printf)($28)
; printf():
lui $4,%hi($LC0)
addiu $4,$4,%lo($LC0)
; printf():
li $5,1 # 0x1
; printf():
li $6,2 # 0x2
; printf():
jalr $25
; printf() (branch delay slot):
li $7,3 # 0x3

; :
lw $31,28($sp)
; 0:
move $2,$0
;
j $31
addiu $sp,$sp,32 ; branch delay slot

6.13: GCC 4.4.5 (IDA)


.text:00000000 main:
.text:00000000
.text:00000000 var_10 = 0x10
.text:00000000 var_4 = 4

53
6. PRINTF() 6. PRINTF()
.text:00000000
; :
.text:00000000 lui $gp, (__gnu_local_gp >> 16)
.text:00000004 addiu $sp, 0x20
.text:00000008 la $gp, (__gnu_local_gp & 0xFFFF)
.text:0000000C sw $ra, 0x20+var_4($sp)
.text:00000010 sw $gp, 0x20+var_10($sp)
; printf():
.text:00000014 lw $t9, (printf & 0xFFFF)($gp)
; printf():
.text:00000018 la $a0, $LC0 # "a=%d; b=%d; c=%d"
; printf():
.text:00000020 li $a1, 1
; printf():
.text:00000024 li $a2, 2
; printf():
.text:00000028 jalr $t9
; printf() (branch delay slot):
.text:0000002C li $a3, 3
; :
.text:00000030 lw $ra, 0x20+var_4($sp)
; 0:
.text:00000034 move $v0, $zero
;
.text:00000038 jr $ra
.text:0000003C addiu $sp, 0x20 ; branch delay slot

IDA LUI ADDIU LA.


0x1C: LA 8 .

GCC 4.4.5

GCC :

6.14: GCC 4.4.5 ( )


$LC0:
.ascii "a=%d; b=%d; c=%d\000"
main:
; :
addiu $sp,$sp,32
sw $31,28($sp)
sw $fp,24($sp)
move $fp,$sp
lui $28,%hi(__gnu_local_gp)
addiu $28,$28,%lo(__gnu_local_gp)
; :
lui $2,%hi($LC0)
addiu $2,$2,%lo($LC0)
; printf():
move $4,$2
; printf():
li $5,1 # 0x1
; printf():
li $6,2 # 0x2
; printf():
li $7,3 # 0x3
; printf():
lw $2,%call16(printf)($28)
nop
; printf():
move $25,$2
jalr $25
nop

; :
lw $28,16($fp)
; 0:
move $2,$0

54
6. PRINTF() 6. PRINTF()
move $sp,$fp
lw $31,28($sp)
lw $fp,24($sp)
addiu $sp,$sp,32
;
j $31
nop

6.15: GCC 4.4.5 (IDA)


.text:00000000 main:
.text:00000000
.text:00000000 var_10 = 0x10
.text:00000000 var_8 = 8
.text:00000000 var_4 = 4
.text:00000000
; :
.text:00000000 addiu $sp, 0x20
.text:00000004 sw $ra, 0x20+var_4($sp)
.text:00000008 sw $fp, 0x20+var_8($sp)
.text:0000000C move $fp, $sp
.text:00000010 la $gp, __gnu_local_gp
.text:00000018 sw $gp, 0x20+var_10($sp)
; :
.text:0000001C la $v0, aADBDCD # "a=%d; b=%d; c=%d"
; printf():
.text:00000024 move $a0, $v0
; printf():
.text:00000028 li $a1, 1
; printf():
.text:0000002C li $a2, 2
; printf():
.text:00000030 li $a3, 3
; printf():
.text:00000034 lw $v0, (printf & 0xFFFF)($gp)
.text:00000038 or $at, $zero
; printf():
.text:0000003C move $t9, $v0
.text:00000040 jalr $t9
.text:00000044 or $at, $zero ; NOP
; :
.text:00000048 lw $gp, 0x20+var_10($fp)
; 0:
.text:0000004C move $v0, $zero
.text:00000050 move $sp, $fp
.text:00000054 lw $ra, 0x20+var_4($sp)
.text:00000058 lw $fp, 0x20+var_8($sp)
.text:0000005C addiu $sp, 0x20
;
.text:00000060 jr $ra
.text:00000064 or $at, $zero ; NOP

6.3.2. 8

9- : 6.1.2 (. 45).
#include <stdio.h>

int main()
{
printf("a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n", 1, 2, 3, 4, 5, 6, 7, 8);
return 0;
};

55
6. PRINTF() 6. PRINTF()
GCC 4.4.5

4 $A0 $A3, .
O32 ( MIPS). ( N32)
.
SW Store Word ( ). MIPS ,
(LI/SW).

6.16: GCC 4.4.5 ( )


$LC0:
.ascii "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\012\000"
main:
; :
lui $28,%hi(__gnu_local_gp)
addiu $sp,$sp,56
addiu $28,$28,%lo(__gnu_local_gp)
sw $31,52($sp)
; 5- :
li $2,4 # 0x4
sw $2,16($sp)
; 6- :
li $2,5 # 0x5
sw $2,20($sp)
; 7- :
li $2,6 # 0x6
sw $2,24($sp)
; 8- :
li $2,7 # 0x7
lw $25,%call16(printf)($28)
sw $2,28($sp)
; 1- $a0:
lui $4,%hi($LC0)
; 9- :
li $2,8 # 0x8
sw $2,32($sp)
addiu $4,$4,%lo($LC0)
; 2- $a1:
li $5,1 # 0x1
; 3- $a2:
li $6,2 # 0x2
; printf():
jalr $25
; 4- $a3 (branch delay slot):
li $7,3 # 0x3

; :
lw $31,52($sp)
; 0:
move $2,$0
;
j $31
addiu $sp,$sp,56 ; branch delay slot

6.17: GCC 4.4.5 (IDA)


.text:00000000 main:
.text:00000000
.text:00000000 var_28 = 0x28
.text:00000000 var_24 = 0x24
.text:00000000 var_20 = 0x20
.text:00000000 var_1C = 0x1C
.text:00000000 var_18 = 0x18
.text:00000000 var_10 = 0x10
.text:00000000 var_4 = 4
.text:00000000
; :
.text:00000000 lui $gp, (__gnu_local_gp >> 16)
.text:00000004 addiu $sp, 0x38
.text:00000008 la $gp, (__gnu_local_gp & 0xFFFF)

56
6. PRINTF() 6. PRINTF()
.text:0000000C sw $ra, 0x38+var_4($sp)
.text:00000010 sw $gp, 0x38+var_10($sp)
; 5- :
.text:00000014 li $v0, 4
.text:00000018 sw $v0, 0x38+var_28($sp)
; 6- :
.text:0000001C li $v0, 5
.text:00000020 sw $v0, 0x38+var_24($sp)
; 7- :
.text:00000024 li $v0, 6
.text:00000028 sw $v0, 0x38+var_20($sp)
; 8- :
.text:0000002C li $v0, 7
.text:00000030 lw $t9, (printf & 0xFFFF)($gp)
.text:00000034 sw $v0, 0x38+var_1C($sp)
; 1- $a0:
.text:00000038 lui $a0, ($LC0 >> 16) # "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g
=%"...
; 9- :
.text:0000003C li $v0, 8
.text:00000040 sw $v0, 0x38+var_18($sp)
; 1- $a1:
.text:00000044 la $a0, ($LC0 & 0xFFFF) # "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g
=%"...
; 2- $a1:
.text:00000048 li $a1, 1
; 3- $a2:
.text:0000004C li $a2, 2
; printf():
.text:00000050 jalr $t9
; 4- $a3 (branch delay slot):
.text:00000054 li $a3, 3
; :
.text:00000058 lw $ra, 0x38+var_4($sp)
; 0:
.text:0000005C move $v0, $zero
;
.text:00000060 jr $ra
.text:00000064 addiu $sp, 0x38 ; branch delay slot

GCC 4.4.5

GCC :

6.18: GCC 4.4.5 ( )


$LC0:
.ascii "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\012\000"
main:
; :
addiu $sp,$sp,56
sw $31,52($sp)
sw $fp,48($sp)
move $fp,$sp
lui $28,%hi(__gnu_local_gp)
addiu $28,$28,%lo(__gnu_local_gp)
lui $2,%hi($LC0)
addiu $2,$2,%lo($LC0)
; 5- :
li $3,4 # 0x4
sw $3,16($sp)
; 6- :
li $3,5 # 0x5
sw $3,20($sp)
; 7- :
li $3,6 # 0x6
sw $3,24($sp)
; 8- :
li $3,7 # 0x7

57
6. PRINTF() 6. PRINTF()
sw $3,28($sp)
; 9- :
li $3,8 # 0x8
sw $3,32($sp)
; 1- $a0:
move $4,$2
; 2- $a1:
li $5,1 # 0x1
; 3- $a2:
li $6,2 # 0x2
; 4- $a3:
li $7,3 # 0x3
; printf():
lw $2,%call16(printf)($28)
nop
move $25,$2
jalr $25
nop
; :
lw $28,40($fp)
; 0:
move $2,$0
move $sp,$fp
lw $31,52($sp)
lw $fp,48($sp)
addiu $sp,$sp,56
;
j $31
nop

6.19: GCC 4.4.5 (IDA)


.text:00000000 main:
.text:00000000
.text:00000000 var_28 = 0x28
.text:00000000 var_24 = 0x24
.text:00000000 var_20 = 0x20
.text:00000000 var_1C = 0x1C
.text:00000000 var_18 = 0x18
.text:00000000 var_10 = 0x10
.text:00000000 var_8 = 8
.text:00000000 var_4 = 4
.text:00000000
; :
.text:00000000 addiu $sp, 0x38
.text:00000004 sw $ra, 0x38+var_4($sp)
.text:00000008 sw $fp, 0x38+var_8($sp)
.text:0000000C move $fp, $sp
.text:00000010 la $gp, __gnu_local_gp
.text:00000018 sw $gp, 0x38+var_10($sp)
.text:0000001C la $v0, aADBDCDDDEDFDGD # "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g
=%"...
; 5- :
.text:00000024 li $v1, 4
.text:00000028 sw $v1, 0x38+var_28($sp)
; 6- :
.text:0000002C li $v1, 5
.text:00000030 sw $v1, 0x38+var_24($sp)
; 7- :
.text:00000034 li $v1, 6
.text:00000038 sw $v1, 0x38+var_20($sp)
; 8- :
.text:0000003C li $v1, 7
.text:00000040 sw $v1, 0x38+var_1C($sp)
; 9- :
.text:00000044 li $v1, 8
.text:00000048 sw $v1, 0x38+var_18($sp)
; 1- $a0:
.text:0000004C move $a0, $v0
; 2- $a1:

58
6. PRINTF() 6. PRINTF()
.text:00000050 li $a1, 1
; 3- $a2:
.text:00000054 li $a2, 2
; 4- $a3:
.text:00000058 li $a3, 3
; printf():
.text:0000005C lw $v0, (printf & 0xFFFF)($gp)
.text:00000060 or $at, $zero
.text:00000064 move $t9, $v0
.text:00000068 jalr $t9
.text:0000006C or $at, $zero ; NOP
; :
.text:00000070 lw $gp, 0x38+var_10($fp)
; 0:
.text:00000074 move $v0, $zero
.text:00000078 move $sp, $fp
.text:0000007C lw $ra, 0x38+var_4($sp)
.text:00000080 lw $fp, 0x38+var_8($sp)
.text:00000084 addiu $sp, 0x38
;
.text:00000088 jr $ra
.text:0000008C or $at, $zero ; NOP

6.4.
:
6.20: x86
...
PUSH
PUSH
PUSH
CALL
; ( )

6.21: x64 (MSVC)


MOV RCX,
MOV RDX,
MOV R8,
MOV R9, 4-
...
PUSH 5-, 6- , .. ( )
CALL
; ( )

6.22: x64 (GCC)


MOV RDI,
MOV RSI,
MOV RDX,
MOV RCX, 4-
MOV R8, 5-
MOV R9, 6-
...
PUSH 7-, 8- , .. ( )
CALL
; ( )

6.23: ARM
MOV R0,
MOV R1,
MOV R2,
MOV R3, 4-
; 5-, 6- , .., ( )
BL
; ( )

59
6. PRINTF() 6. PRINTF()
6.24: ARM64
MOV X0,
MOV X1,
MOV X2,
MOV X3, 4-
MOV X4, 5-
MOV X5, 6-
MOV X6, 7-
MOV X7, 8-
; 9-, 10- , .., ( )
BL CALL
; ( )

6.25: MIPS ( O32)


LI $4, ; AKA $A0
LI $5, ; AKA $A1
LI $6, ; AKA $A2
LI $7, 4- ; AKA $A3
; 5-, 6- , .., ( )
LW temp_reg,
JALR temp_reg

6.5.
, x86, x64, fastcall, ARM MIPS
, , , , .
, , -
.
$A0$A3 MIPS ( O32). -
( , $ZERO)
.
CPU .
,
, , . .

60
7. SCANF() 7. SCANF()

scanf()

scanf().

7.1.

#include <stdio.h>

int main()
{
int x;
printf ("Enter X:\n");

scanf ("%d", &x);

printf ("You entered %d...\n", x);

return 0;
};

scanf() , - .
int.

7.1.1.

. ,
, , .
, (callee) - ,
. , , -callee
, callee - .
/++ - .
x86 32- (.. 4 ), x86-64 64- (
8 ). , , x86-64
2 , -.
(void*); ,
memcpy(), , 2 void*,
, . ,
.
, (
(10 (. 104)) ). scanf() . , ,
, .
/++ . , ,
.

61
7. SCANF() 7. SCANF()
7.1.2. x86

MSVC

, MSVC 2010:
CONST SEGMENT
$SG3831 DB 'Enter X:', 0aH, 00H
$SG3832 DB '%d', 00H
$SG3833 DB 'You entered %d...', 0aH, 00H
CONST ENDS
PUBLIC _main
EXTRN _scanf:PROC
EXTRN _printf:PROC
; Function compile flags: /Odtp
_TEXT SEGMENT
_x$ = 4 ; size = 4
_main PROC
push ebp
mov ebp, esp
push ecx
push OFFSET $SG3831 ; 'Enter X:'
call _printf
add esp, 4
lea eax, DWORD PTR _x$[ebp]
push eax
push OFFSET $SG3832 ; '%d'
call _scanf
add esp, 8
mov ecx, DWORD PTR _x$[ebp]
push ecx
push OFFSET $SG3833 ; 'You entered %d...'
call _printf
add esp, 8

; 0
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS

x .
/++ . ,
. , , x86 .
PUSH ECX ECX. (
POP ECX ).
4 x .
x _x$ ( -4) EBP
.
EBP EBP+
, .
ESP, , .
, EBP ESP .
32- :

62
7. SCANF() 7. SCANF()

EBP-8 #2, IDA var_8
EBP-4 #1, IDA var_4
EBP EBP
EBP+4
EBP+8 #1, IDA arg_0
EBP+0xC #2, IDA arg_4
EBP+0x10 #3, IDA arg_8

scanf() .
, %d x.
x EAX lea eax, DWORD PTR _x$[ebp].
LEA load effective address, - (A.6.2 (. 965)).
, LEA EAX EBP
_x$.
lea eax, [ebp-4].
, EBP 4 EAX. EAX
scanf().
printf(). : You entered %d...\n.
: mov ecx, [ebp-4]. ECX x, .
ECX printf().

63
7. SCANF() 7. SCANF()
7.1.3. MSVC + OllyDbg

OllyDbg. , F8 ( , ) ,
, ntdll.dll. , main().
(PUSH EBP), F2 (set a breakpoint), F9 (Run)
main().
, x:

. 7.1: OllyDbg:

EAX Follow in stack.


. , . . -
(0x6E494714). , PUSH .
F8 scanf(). scanf() , , , ,
123:

. 7.2:

64
7. SCANF() 7. SCANF()
scanf() :

. 7.3: OllyDbg: scanf()

scanf() 1 EAX, , .
0x7B (123).

65
7. SCANF() 7. SCANF()
ECX printf() :

. 7.4: OllyDbg: printf()

GCC

Linux GCC 4.4.1:


main proc near

var_20 = dword ptr 20h


var_1C = dword ptr 1Ch
var_4 = dword ptr 4

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 20h
mov [esp+20h+var_20], offset aEnterX ; "Enter X:"
call _puts
mov eax, offset aD ; "%d"
lea edx, [esp+20h+var_4]
mov [esp+20h+var_1C], edx
mov [esp+20h+var_20], eax
call ___isoc99_scanf
mov edx, [esp+20h+var_4]
mov eax, offset aYouEnteredD___ ; "You entered %d...\n"
mov [esp+20h+var_1C], edx
mov [esp+20h+var_20], eax
call _printf
mov eax, 0
leave
retn
main endp

GCC printf() puts(). , (3.4.3 (. 15)).


MOV.

, , /++-
. /++ ,
, .

66
7. SCANF() 7. SCANF()
7.1.4. x64

, .

MSVC

7.1: MSVC 2012 x64


_DATA SEGMENT
$SG1289 DB 'Enter X:', 0aH, 00H
$SG1291 DB '%d', 00H
$SG1292 DB 'You entered %d...', 0aH, 00H
_DATA ENDS

_TEXT SEGMENT
x$ = 32
main PROC
$LN3:
sub rsp, 56
lea rcx, OFFSET FLAT:$SG1289 ; 'Enter X:'
call printf
lea rdx, QWORD PTR x$[rsp]
lea rcx, OFFSET FLAT:$SG1291 ; '%d'
call scanf
mov edx, DWORD PTR x$[rsp]
lea rcx, OFFSET FLAT:$SG1292 ; 'You entered %d...'
call printf

; 0
xor eax, eax
add rsp, 56
ret 0
main ENDP
_TEXT ENDS

GCC

7.2: GCC 4.4.6 x64


.LC0:
.string "Enter X:"
.LC1:
.string "%d"
.LC2:
.string "You entered %d...\n"

main:
sub rsp, 24
mov edi, OFFSET FLAT:.LC0 ; "Enter X:"
call puts
lea rsi, [rsp+12]
mov edi, OFFSET FLAT:.LC1 ; "%d"
xor eax, eax
call __isoc99_scanf
mov esi, DWORD PTR [rsp+12]
mov edi, OFFSET FLAT:.LC2 ; "You entered %d...\n"
xor eax, eax
call printf

; 0
xor eax, eax
add rsp, 24
ret

67
7. SCANF() 7. SCANF()
7.1.5. ARM

Keil 6/2013 ( Thumb)

.text:00000042 scanf_main
.text:00000042
.text:00000042 var_8 = 8
.text:00000042
.text:00000042 08 B5 PUSH {R3,LR}
.text:00000044 A9 A0 ADR R0, aEnterX ; "Enter X:\n"
.text:00000046 06 F0 D3 F8 BL __2printf
.text:0000004A 69 46 MOV R1, SP
.text:0000004C AA A0 ADR R0, aD ; "%d"
.text:0000004E 06 F0 CD F8 BL __0scanf
.text:00000052 00 99 LDR R1, [SP,#8+var_8]
.text:00000054 A9 A0 ADR R0, aYouEnteredD___ ; "You entered %d...\n"
.text:00000056 06 F0 CB F8 BL __2printf
.text:0000005A 00 20 MOVS R0, #0
.text:0000005C 08 BD POP {R3,PC}

scanf() , int. int 32- ,


4 , 32- . x
, IDA var_8. , , .. SP
, . SP R1,
format-, scanf(). , LDR,
R1, printf().

ARM64

7.3: GCC 4.9.1 ARM64


1 .LC0:
2 .string "Enter X:"
3 .LC1:
4 .string "%d"
5 .LC2:
6 .string "You entered %d...\n"
7 scanf_main:
8 ; 32 SP, FP LR :
9 stp x29, x30, [sp, 32]!
10 ; (FP=SP)
11 add x29, sp, 0
12 ; "Enter X:"
13 adrp x0, .LC0
14 add x0, x0, :lo12:.LC0
15 ; X0= "Enter X:"
16 ; :
17 bl puts
18 ; "%d":
19 adrp x0, .LC1
20 add x0, x0, :lo12:.LC1
21 ; "x" (X1=FP+28):
22 add x1, x29, 28
23 ; X1= "x"
24 ; scanf() :
25 bl __isoc99_scanf
26 ; 32- :
27 ldr w1, [x29,28]
28 ; W1=x
29 ; "You entered %d...\n"
30 ; printf() X0 "x" X1 ( W1)
31 adrp x0, .LC2
32 add x0, x0, :lo12:.LC2
33 bl printf
34 ; 0
35 mov w0, 0
36 ; FP LR, 32 SP:
37 ldp x29, x30, [sp], 32

68
7. SCANF() 7. SCANF()
38 ret

32 , . ,
? x ( 22). 28?
-, , .
scanf(), , , .
32- int. 27 printf().

7.1.6. MIPS

x , $sp + 24.
scanf(), LW (Load Word
) printf().

7.4: GCC 4.4.5 ( )


$LC0:
.ascii "Enter X:\000"
$LC1:
.ascii "%d\000"
$LC2:
.ascii "You entered %d...\012\000"
main:
; :
lui $28,%hi(__gnu_local_gp)
addiu $sp,$sp,40
addiu $28,$28,%lo(__gnu_local_gp)
sw $31,36($sp)
; puts():
lw $25,%call16(puts)($28)
lui $4,%hi($LC0)
jalr $25
addiu $4,$4,%lo($LC0) ; branch delay slot
; scanf():
lw $28,16($sp)
lui $4,%hi($LC1)
lw $25,%call16(__isoc99_scanf)($28)
; scanf(), $a1=$sp+24:
addiu $5,$sp,24
jalr $25
addiu $4,$4,%lo($LC1) ; branch delay slot

; printf():
lw $28,16($sp)
; printf(),
; $sp+24:
lw $5,24($sp)
lw $25,%call16(printf)($28)
lui $4,%hi($LC2)
jalr $25
addiu $4,$4,%lo($LC2) ; branch delay slot

; :
lw $31,36($sp)
; 0:
move $2,$0
; :
j $31
addiu $sp,$sp,40 ; branch delay slot

IDA :

7.5: GCC 4.4.5 (IDA)


.text:00000000 main:
.text:00000000
.text:00000000 var_18 = 0x18
.text:00000000 var_10 = 0x10
.text:00000000 var_4 = 4

69
7. SCANF() 7. SCANF()
.text:00000000
; :
.text:00000000 lui $gp, (__gnu_local_gp >> 16)
.text:00000004 addiu $sp, 0x28
.text:00000008 la $gp, (__gnu_local_gp & 0xFFFF)
.text:0000000C sw $ra, 0x28+var_4($sp)
.text:00000010 sw $gp, 0x28+var_18($sp)
; puts():
.text:00000014 lw $t9, (puts & 0xFFFF)($gp)
.text:00000018 lui $a0, ($LC0 >> 16) # "Enter X:"
.text:0000001C jalr $t9
.text:00000020 la $a0, ($LC0 & 0xFFFF) # "Enter X:" ; branch delay slot
; scanf():
.text:00000024 lw $gp, 0x28+var_18($sp)
.text:00000028 lui $a0, ($LC1 >> 16) # "%d"
.text:0000002C lw $t9, (__isoc99_scanf & 0xFFFF)($gp)
; scanf(), $a1=$sp+24:
.text:00000030 addiu $a1, $sp, 0x28+var_10
.text:00000034 jalr $t9 ; branch delay slot
.text:00000038 la $a0, ($LC1 & 0xFFFF) # "%d"
; printf():
.text:0000003C lw $gp, 0x28+var_18($sp)
; printf(),
; $sp+24:
.text:00000040 lw $a1, 0x28+var_10($sp)
.text:00000044 lw $t9, (printf & 0xFFFF)($gp)
.text:00000048 lui $a0, ($LC2 >> 16) # "You entered %d...\n"
.text:0000004C jalr $t9
.text:00000050 la $a0, ($LC2 & 0xFFFF) # "You entered %d...\n" ; branch delay
slot
; :
.text:00000054 lw $ra, 0x28+var_4($sp)
; 0:
.text:00000058 move $v0, $zero
; :
.text:0000005C jr $ra
.text:00000060 addiu $sp, 0x28 ; branch delay slot

7.2.
x , ?
, . -,
.
#include <stdio.h>

// x
int x;

int main()
{
printf ("Enter X:\n");

scanf ("%d", &x);

printf ("You entered %d...\n", x);

return 0;
};

7.2.1. MSVC: x86

_DATA SEGMENT
COMM _x:DWORD
$SG2456 DB 'Enter X:', 0aH, 00H

70
7. SCANF() 7. SCANF()
$SG2457 DB '%d', 00H
$SG2458 DB 'You entered %d...', 0aH, 00H
_DATA ENDS
PUBLIC _main
EXTRN _scanf:PROC
EXTRN _printf:PROC
; Function compile flags: /Odtp
_TEXT SEGMENT
_main PROC
push ebp
mov ebp, esp
push OFFSET $SG2456
call _printf
add esp, 4
push OFFSET _x
push OFFSET $SG2457
call _scanf
add esp, 8
mov eax, DWORD PTR _x
push eax
push OFFSET $SG2458
call _printf
add esp, 8
xor eax, eax
pop ebp
ret 0
_main ENDP
_TEXT ENDS

. x _DATA. .
, . -
( ,
?), , - , ,
1 .
:
int x=10; //

:
_DATA SEGMENT
_x DD 0aH

...

0xA DD (dword = 32 ).
.exe- IDA, , x _DATA,
.
IDA.exe , x , :
.data:0040FA80 _x dd ? ; DATA XREF: _main+10
.data:0040FA80 ; _main+22
.data:0040FA84 dword_40FA84 dd ? ; DATA XREF: _memset+1E
.data:0040FA84 ; unknown_libname_1+28
.data:0040FA88 dword_40FA88 dd ? ; DATA XREF: ___sbh_find_block+5
.data:0040FA88 ; ___sbh_free_block+2BC
.data:0040FA8C ; LPVOID lpMem
.data:0040FA8C lpMem dd ? ; DATA XREF: ___sbh_find_block+B
.data:0040FA8C ; ___sbh_free_block+2CA
.data:0040FA90 dword_40FA90 dd ? ; DATA XREF: _V6_HeapAlloc+13
.data:0040FA90 ; __calloc_impl+72
.data:0040FA94 dword_40FA94 dd ? ; DATA XREF: ___sbh_free_block+2FE

_x ?, . ,
.exe , [ISO07, 6.7.8p10].
.exe . .
, .
1 VM

71
7. SCANF() 7. SCANF()
7.2.2. MSVC: x86 + OllyDbg

. 7.5: OllyDbg: scanf()

. , PUSH ( x)
, , Follow in dump.
.
123, 0x7B.
7B? , 00 00 00 7B.
endianness, x86 little-endian. , , -
. : 31 (. 473).
32- EAX printf().
x 0x00C53394.

72
7. SCANF() 7. SCANF()
OllyDbg (Alt-M) , PE- .data
:

. 7.6: OllyDbg:

7.2.3. GCC: x86

Linux . , x ,
_bss. ELF :
; Segment type: Uninitialized
; Segment permissions: Read/Write

- , , 10,
_data, :
; Segment type: Pure data
; Segment permissions: Read/Write

7.2.4. MSVC: x64

7.6: MSVC 2012 x64


_DATA SEGMENT
COMM x:DWORD
$SG2924 DB 'Enter X:', 0aH, 00H
$SG2925 DB '%d', 00H
$SG2926 DB 'You entered %d...', 0aH, 00H
_DATA ENDS

_TEXT SEGMENT
main PROC
$LN3:
sub rsp, 40

lea rcx, OFFSET FLAT:$SG2924 ; 'Enter X:'


call printf

73
7. SCANF() 7. SCANF()
lea rdx, OFFSET FLAT:x
lea rcx, OFFSET FLAT:$SG2925 ; '%d'
call scanf
mov edx, DWORD PTR x
lea rcx, OFFSET FLAT:$SG2926 ; 'You entered %d...'
call printf

; 0
xor eax, eax

add rsp, 40
ret 0
main ENDP
_TEXT ENDS

x86. scanf() x
LEA, printf() MOV . DWORD PTR
( ) ,
32-, MOV .

7.2.5. ARM: Keil 6/2013 ( Thumb)

.text:00000000 ; Segment type: Pure code


.text:00000000 AREA .text, CODE
...
.text:00000000 main
.text:00000000 PUSH {R4,LR}
.text:00000002 ADR R0, aEnterX ; "Enter X:\n"
.text:00000004 BL __2printf
.text:00000008 LDR R1, =x
.text:0000000A ADR R0, aD ; "%d"
.text:0000000C BL __0scanf
.text:00000010 LDR R0, =x
.text:00000012 LDR R1, [R0]
.text:00000014 ADR R0, aYouEnteredD___ ; "You entered %d...\n"
.text:00000016 BL __2printf
.text:0000001A MOVS R0, #0
.text:0000001C POP {R4,PC}
...
.text:00000020 aEnterX DCB "Enter X:",0xA,0 ; DATA XREF: main+2
.text:0000002A DCB 0
.text:0000002B DCB 0
.text:0000002C off_2C DCD x ; DATA XREF: main+8
.text:0000002C ; main+10
.text:00000030 aD DCB "%d",0 ; DATA XREF: main+A
.text:00000033 DCB 0
.text:00000034 aYouEnteredD___ DCB "You entered %d...",0xA,0 ; DATA XREF: main+14
.text:00000047 DCB 0
.text:00000047 ; .text ends
.text:00000047
...
.data:00000048 ; Segment type: Pure data
.data:00000048 AREA .data, DATA
.data:00000048 ; ORG 0x48
.data:00000048 EXPORT x
.data:00000048 x DCD 0xA ; DATA XREF: main+8
.data:00000048 ; main+10
.data:00000048 ; .data ends

, x , , -, ,
(.data). , (.text), x ?
, , . , . -
, , .text.
( , embedded-,
), . , -
, . ,
, , , , .

74
7. SCANF() 7. SCANF()
x (off_2C)
. , x -
, . LDR Thumb-
1020 .
ARM- 4095 . , x
, , 2
- , !
: const, Keil .constdata.
, .

7.2.6. ARM64

7.7: GCC 4.9.1 ARM64


1 .comm x,4,4
2 .LC0:
3 .string "Enter X:"
4 .LC1:
5 .string "%d"
6 .LC2:
7 .string "You entered %d...\n"
8 f5:
9 ; FP LR :
10 stp x29, x30, [sp, 16]!
11 ; (FP=SP)
12 add x29, sp, 0
13 ; "Enter X:":
14 adrp x0, .LC0
15 add x0, x0, :lo12:.LC0
16 bl puts
17 ; "%d":
18 adrp x0, .LC1
19 add x0, x0, :lo12:.LC1
20 ; x:
21 adrp x1, x
22 add x1, x1, :lo12:x
23 bl __isoc99_scanf
24 ; x:
25 adrp x0, x
26 add x0, x0, :lo12:x
27 ; :
28 ldr w1, [x0]
29 ; "You entered %d...\n":
30 adrp x0, .LC2
31 add x0, x0, :lo12:.LC2
32 bl printf
33 ; 0
34 mov w0, 0
35 ; FP LR:
36 ldp x29, x30, [sp], 16
37 ret

x , ADRP/ADD ( 21 25).

7.2.7. MIPS

x . IDA. IDA
x ELF- .sbss ( Global Pointer? 3.5.1 (. 18)),
.

7.8: GCC 4.4.5 (IDA)

2 linker

75
7. SCANF() 7. SCANF()
.text:004006C0 main:
.text:004006C0
.text:004006C0 var_10 = 0x10
.text:004006C0 var_4 = 4
.text:004006C0
; :
.text:004006C0 lui $gp, 0x42
.text:004006C4 addiu $sp, 0x20
.text:004006C8 li $gp, 0x418940
.text:004006CC sw $ra, 0x20+var_4($sp)
.text:004006D0 sw $gp, 0x20+var_10($sp)
; puts():
.text:004006D4 la $t9, puts
.text:004006D8 lui $a0, 0x40
.text:004006DC jalr $t9 ; puts
.text:004006E0 la $a0, aEnterX # "Enter X:" ; branch delay slot
; scanf():
.text:004006E4 lw $gp, 0x20+var_10($sp)
.text:004006E8 lui $a0, 0x40
.text:004006EC la $t9, __isoc99_scanf
; x:
.text:004006F0 la $a1, x
.text:004006F4 jalr $t9 ; __isoc99_scanf
.text:004006F8 la $a0, aD # "%d" ; branch delay slot
; printf():
.text:004006FC lw $gp, 0x20+var_10($sp)
.text:00400700 lui $a0, 0x40
; x:
.text:00400704 la $v0, x
.text:00400708 la $t9, printf
; "x" printf() $a1:
.text:0040070C lw $a1, (x 0x41099C)($v0)
.text:00400710 jalr $t9 ; printf
.text:00400714 la $a0, aYouEnteredD___ # "You entered %d...\n" ; branch delay
slot
; :
.text:00400718 lw $ra, 0x20+var_4($sp)
.text:0040071C move $v0, $zero
.text:00400720 jr $ra
.text:00400724 addiu $sp, 0x20 ; branch delay slot

...

.sbss:0041099C # Segment type: Uninitialized


.sbss:0041099C .sbss
.sbss:0041099C .globl x
.sbss:0041099C x: .space 4
.sbss:0041099C

IDA , objdump -
:
7.9: GCC 4.4.5 (objdump)
1 004006c0 <main>:
2 ; :
3 4006c0: 3c1c0042 lui gp,0x42
4 4006c4: 27bdffe0 addiu sp,sp,32
5 4006c8: 279c8940 addiu gp,gp,30400
6 4006cc: afbf001c sw ra,28(sp)
7 4006d0: afbc0010 sw gp,16(sp)
8 ; puts():
9 4006d4: 8f998034 lw t9,32716(gp)
10 4006d8: 3c040040 lui a0,0x40
11 4006dc: 0320f809 jalr t9
12 4006e0: 248408f0 addiu a0,a0,2288 ; branch delay slot
13 ; scanf():
14 4006e4: 8fbc0010 lw gp,16(sp)
15 4006e8: 3c040040 lui a0,0x40
16 4006ec: 8f998038 lw t9,32712(gp)
17 ; x:

76
7. SCANF() 7. SCANF()
18 4006f0: 8f858044 lw a1,32700(gp)
19 4006f4: 0320f809 jalr t9
20 4006f8: 248408fc addiu a0,a0,2300 ; branch delay slot
21 ; printf():
22 4006fc: 8fbc0010 lw gp,16(sp)
23 400700: 3c040040 lui a0,0x40
24 ; x:
25 400704: 8f828044 lw v0,32700(gp)
26 400708: 8f99803c lw t9,32708(gp)
27 ; "x" printf() $a1:
28 40070c: 8c450000 lw a1,0(v0)
29 400710: 0320f809 jalr t9
30 400714: 24840900 addiu a0,a0,2304 ; branch delay slot
31 ; :
32 400718: 8fbf001c lw ra,28(sp)
33 40071c: 00001021 move v0,zero
34 400720: 03e00008 jr ra
35 400724: 27bd0020 addiu sp,sp,32 ; branch delay slot
36 ; NOP- - 16- :
37 400728: 00200825 move at,at
38 40072c: 00200825 move at,at

, x 64KiB, GP
( 18). : , (puts(),
scanf(), printf()) 64KiB GP ( 9, 16 26). GP ,
, , x
- . , .
NOP- (MOVE $AT,$AT ),
16- .

, x :
int x=10; //

IDA x .data:

7.10: GCC 4.4.5 (IDA)


.text:004006A0 main:
.text:004006A0
.text:004006A0 var_10 = 0x10
.text:004006A0 var_8 = 8
.text:004006A0 var_4 = 4
.text:004006A0
.text:004006A0 lui $gp, 0x42
.text:004006A4 addiu $sp, 0x20
.text:004006A8 li $gp, 0x418930
.text:004006AC sw $ra, 0x20+var_4($sp)
.text:004006B0 sw $s0, 0x20+var_8($sp)
.text:004006B4 sw $gp, 0x20+var_10($sp)
.text:004006B8 la $t9, puts
.text:004006BC lui $a0, 0x40
.text:004006C0 jalr $t9 ; puts
.text:004006C4 la $a0, aEnterX # "Enter X:"
.text:004006C8 lw $gp, 0x20+var_10($sp)
; x:
.text:004006CC lui $s0, 0x41
.text:004006D0 la $t9, __isoc99_scanf
.text:004006D4 lui $a0, 0x40
; x:
.text:004006D8 addiu $a1, $s0, (x 0x410000)
; x $a1.
.text:004006DC jalr $t9 ; __isoc99_scanf
.text:004006E0 la $a0, aD # "%d"
.text:004006E4 lw $gp, 0x20+var_10($sp)
; :

77
7. SCANF() 7. SCANF()
.text:004006E8 lw $a1, x
; x $a1.
.text:004006EC la $t9, printf
.text:004006F0 lui $a0, 0x40
.text:004006F4 jalr $t9 ; printf
.text:004006F8 la $a0, aYouEnteredD___ # "You entered %d...\n"
.text:004006FC lw $ra, 0x20+var_4($sp)
.text:00400700 move $v0, $zero
.text:00400704 lw $s0, 0x20+var_8($sp)
.text:00400708 jr $ra
.text:0040070C addiu $sp, 0x20

...

.data:00410920 .globl x
.data:00410920 x: .word 0xA

.sdata? , - GCC? , x .data,


.
. LUI (Load Upper Immediate
16 ) ADDIU (Add Immediate Unsigned Word ).
objdump- :

7.11: GCC 4.4.5 (objdump)


004006a0 <main>:
4006a0: 3c1c0042 lui gp,0x42
4006a4: 27bdffe0 addiu sp,sp,32
4006a8: 279c8930 addiu gp,gp,30416
4006ac: afbf001c sw ra,28(sp)
4006b0: afb00018 sw s0,24(sp)
4006b4: afbc0010 sw gp,16(sp)
4006b8: 8f998034 lw t9,32716(gp)
4006bc: 3c040040 lui a0,0x40
4006c0: 0320f809 jalr t9
4006c4: 248408d0 addiu a0,a0,2256
4006c8: 8fbc0010 lw gp,16(sp)
; x:
4006cc: 3c100041 lui s0,0x41
4006d0: 8f998038 lw t9,32712(gp)
4006d4: 3c040040 lui a0,0x40
; x:
4006d8: 26050920 addiu a1,s0,2336
; x $a1.
4006dc: 0320f809 jalr t9
4006e0: 248408dc addiu a0,a0,2268
4006e4: 8fbc0010 lw gp,16(sp)
; x $s0.
; :
4006e8: 8e050920 lw a1,2336(s0)
; x $a1.
4006ec: 8f99803c lw t9,32708(gp)
4006f0: 3c040040 lui a0,0x40
4006f4: 0320f809 jalr t9
4006f8: 248408e0 addiu a0,a0,2272
4006fc: 8fbf001c lw ra,28(sp)
400700: 00001021 move v0,zero
400704: 8fb00018 lw s0,24(sp)
400708: 03e00008 jr ra
40070c: 27bd0020 addiu sp,sp,32

LUI ADDIU, $S0,


LW (Load Word), LW
printf().
T-, S-,
(.. saved). $S0 0x4006cc
0x4006e8 scanf(). scanf() .

78
7. SCANF() 7. SCANF()
7.3. scanf()
, scanf() .
, , scanf() - ,
scanf() .
#include <stdio.h>

int main()
{
int x;
printf ("Enter X:\n");

if (scanf ("%d", &x)==1)


printf ("You entered %d...\n", x);
else
printf ("What you entered? Huh?\n");

return 0;
};

, scanf()3 .
, , scanf() 1. , 0 ( EOF4 ).
, scanf() - .
:
C:\...>ex3.exe
Enter X:
123
You entered 123...

C:\...>ex3.exe
Enter X:
ouch
What you entered? Huh?

7.3.1. MSVC: x86

(MSVC 2010):
lea eax, DWORD PTR _x$[ebp]
push eax
push OFFSET $SG3833 ; '%d', 00H
call _scanf
add esp, 8
cmp eax, 1
jne SHORT $LN2@main
mov ecx, DWORD PTR _x$[ebp]
push ecx
push OFFSET $SG3834 ; 'You entered %d...', 0aH, 00H
call _printf
add esp, 8
jmp SHORT $LN1@main
$LN2@main:
push OFFSET $SG3836 ; 'What you entered? Huh?', 0aH, 00H
call _printf
add esp, 4
$LN1@main:
xor eax, eax

, (
scanf()) EAX.
3 scanf, wscanf: MSDN
4 End of le ( )

79
7. SCANF() 7. SCANF()
CMP EAX, 1 (CoMPare), EAX 1.
CMP: JNE. Jump if Not Equal,
.
, EAX 1, JNE CPU JNE, $LN2@main.
, CPU printf() What you entered? Huh?.
, printf() : 'You entered
%d...' x.
printf(), JMP, -
, printf() XOR EAX, EAX,
return 0.
, - -
CMP Jcc, cc condition code. CMP -
5 . Jcc ( ).
, , CMP SUB,
. ,
CMP. 1 1, , 0, ZF (zero ag),
, 0. EAX, ZF
, , . JNE ZF,
. , JNE JNZ (Jump if Not Zero).
. , CMP SUB ,
, SUB - . CMP SUB ,
.

7.3.2. MSVC: x86: IDA

, IDA. , MSVC
/MD, ,
MSVCR*.DLL. , .
IDA, ( ). . , ,
, JNZ . , n
error. exit. :
.text:00401000 _main proc near
.text:00401000
.text:00401000 var_4 = dword ptr 4
.text:00401000 argc = dword ptr 8
.text:00401000 argv = dword ptr 0Ch
.text:00401000 envp = dword ptr 10h
.text:00401000
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 push ecx
.text:00401004 push offset Format ; "Enter X:\n"
.text:00401009 call ds:printf
.text:0040100F add esp, 4
.text:00401012 lea eax, [ebp+var_4]
.text:00401015 push eax
.text:00401016 push offset aD ; "%d"
.text:0040101B call ds:scanf
.text:00401021 add esp, 8
.text:00401024 cmp eax, 1
.text:00401027 jnz short error
.text:00401029 mov ecx, [ebp+var_4]
.text:0040102C push ecx
.text:0040102D push offset aYou ; "You entered %d...\n"
.text:00401032 call ds:printf
.text:00401038 add esp, 8
.text:0040103B jmp short exit
.text:0040103D
.text:0040103D error: ; CODE XREF: _main+27
.text:0040103D push offset aWhat ; "What you entered? Huh?\n"
.text:00401042 call ds:printf
5 . x86-: wikipedia.

80
7. SCANF() 7. SCANF()
.text:00401048 add esp, 4
.text:0040104B
.text:0040104B exit: ; CODE XREF: _main+3B
.text:0040104B xor eax, eax
.text:0040104D mov esp, ebp
.text:0040104F pop ebp
.text:00401050 retn
.text:00401050 _main endp

. ,
.
IDA : ,
.
:
.text:00401000 _text segment para public 'CODE' use32
.text:00401000 assume cs:_text
.text:00401000 ;org 401000h
.text:00401000 ; ask for X
.text:00401012 ; get X
.text:00401024 cmp eax, 1
.text:00401027 jnz short error
.text:00401029 ; print result
.text:0040103B jmp short exit
.text:0040103D
.text:0040103D error: ; CODE XREF: _main+27
.text:0040103D push offset aWhat ; "What you entered? Huh?\n"
.text:00401042 call ds:printf
.text:00401048 add esp, 4
.text:0040104B
.text:0040104B exit: ; CODE XREF: _main+3B
.text:0040104B xor eax, eax
.text:0040104D mov esp, ebp
.text:0040104F pop ebp
.text:00401050 retn
.text:00401050 _main endp

+ .

81
7. SCANF() 7. SCANF()
, , IDA :

. 7.7: IDA

: . , -
, .

82
7. SCANF() 7. SCANF()
(group nodes). :

. 7.8: IDA

. , ( ) ,
.

83
7. SCANF() 7. SCANF()
7.3.3. MSVC: x86 + OllyDbg

OllyDbg , scanf() .
scanf() , .
0x6E494714:

. 7.9: OllyDbg: scanf()

84
7. SCANF() 7. SCANF()
scanf() , - , asdasd. scanf()
0 EAX, , :

. 7.10: OllyDbg: scanf()

. ,
scanf()? .
. EAX, , ,
Set to 1. .
EAX 1, , printf() .
(F9) :

. 7.11:

, 1850296084 (0x6E494714)!

85
7. SCANF() 7. SCANF()
7.3.4. MSVC: x86 + Hiew

.
, , .
MSVCR*.DLL (.. /MD)6 ,
main() .text. Hiew,
.text (Enter, F8, F6, Enter, Enter).
:

. 7.12: Hiew: main()

Hiew ASCIIZ7 - , .

6 , dynamic linking
7 ASCII Zero (ASCII- )

86
7. SCANF() 7. SCANF()
.00401027 ( JNZ, ), F3, -
9090( NOP-):

. 7.13: Hiew: JNZ NOP-

F9 (update). . , .
NOP- , , . 0
( ), JNZ .
: EB, ( ) .
. ,
.

7.3.5. MSVC: x64

int, x86-64 32-, , -


E-. , , 64-
R-.

7.12: MSVC 2012 x64


_DATA SEGMENT
$SG2924 DB 'Enter X:', 0aH, 00H
$SG2926 DB '%d', 00H
$SG2927 DB 'You entered %d...', 0aH, 00H
$SG2929 DB 'What you entered? Huh?', 0aH, 00H
_DATA ENDS

_TEXT SEGMENT
x$ = 32
main PROC
$LN5:

87
7. SCANF() 7. SCANF()
sub rsp, 56
lea rcx, OFFSET FLAT:$SG2924 ; 'Enter X:'
call printf
lea rdx, QWORD PTR x$[rsp]
lea rcx, OFFSET FLAT:$SG2926 ; '%d'
call scanf
cmp eax, 1
jne SHORT $LN2@main
mov edx, DWORD PTR x$[rsp]
lea rcx, OFFSET FLAT:$SG2927 ; 'You entered %d...'
call printf
jmp SHORT $LN1@main
$LN2@main:
lea rcx, OFFSET FLAT:$SG2929 ; 'What you entered? Huh?'
call printf
$LN1@main:
; 0
xor eax, eax
add rsp, 56
ret 0
main ENDP
_TEXT ENDS
END

7.3.6. ARM

ARM: Keil 6/2013 ( Thumb)

7.13: Keil 6/2013 ( Thumb)


var_8 = 8

PUSH {R3,LR}
ADR R0, aEnterX ; "Enter X:\n"
BL __2printf
MOV R1, SP
ADR R0, aD ; "%d"
BL __0scanf
CMP R0, #1
BEQ loc_1E
ADR R0, aWhatYouEntered ; "What you entered? Huh?\n"
BL __2printf

loc_1A ; CODE XREF: main+26


MOVS R0, #0
POP {R3,PC}

loc_1E ; CODE XREF: main+12


LDR R1, [SP,#8+var_8]
ADR R0, aYouEnteredD___ ; "You entered %d...\n"
BL __2printf
B loc_1A

: CMP BEQ8 .
CMP x86: .
BEQ , ,
0, Z 1. JZ x86.
: , , R0 0
.

ARM64

8 (PowerPC, ARM) Branch if Equal

88
7. SCANF() 7. SCANF()
7.14: GCC 4.9.1 ARM64
1 .LC0:
2 .string "Enter X:"
3 .LC1:
4 .string "%d"
5 .LC2:
6 .string "You entered %d...\n"
7 .LC3:
8 .string "What you entered? Huh?"
9 f6:
10 ; FP LR :
11 stp x29, x30, [sp, 32]!
12 ; (FP=SP)
13 add x29, sp, 0
14 ; "Enter X:"
15 adrp x0, .LC0
16 add x0, x0, :lo12:.LC0
17 bl puts
18 ; "%d":
19 adrp x0, .LC1
20 add x0, x0, :lo12:.LC1
21 ; x
22 add x1, x29, 28
23 bl __isoc99_scanf
24 ; scanf() W0.
25 ; :
26 cmp w0, 1
27 ; BNE Branch if Not Equal (, )
28 ; W0<>0, L2
29 bne .L2
30 ; W0=1, ,
31 ; x
32 ldr w1, [x29,28]
33 ; "You entered %d...\n":
34 adrp x0, .LC2
35 add x0, x0, :lo12:.LC2
36 bl printf
37 ; , "What you entered? Huh?" :
38 b .L3
39 .L2:
40 ; "What you entered? Huh?" :
41 adrp x0, .LC3
42 add x0, x0, :lo12:.LC3
43 bl puts
44 .L3:
45 ; 0
46 mov w0, 0
47 ; FP LR:
48 ldp x29, x30, [sp], 32
49 ret

, CMP/BNE (Branch if Not Equal: ).

7.3.7. MIPS

7.15: GCC 4.4.5 (IDA)


.text:004006A0 main:
.text:004006A0
.text:004006A0 var_18 = 0x18
.text:004006A0 var_10 = 0x10
.text:004006A0 var_4 = 4
.text:004006A0
.text:004006A0 lui $gp, 0x42
.text:004006A4 addiu $sp, 0x28
.text:004006A8 li $gp, 0x418960
.text:004006AC sw $ra, 0x28+var_4($sp)
.text:004006B0 sw $gp, 0x28+var_18($sp)

89
7. SCANF() 7. SCANF()
.text:004006B4 la $t9, puts
.text:004006B8 lui $a0, 0x40
.text:004006BC jalr $t9 ; puts
.text:004006C0 la $a0, aEnterX # "Enter X:"
.text:004006C4 lw $gp, 0x28+var_18($sp)
.text:004006C8 lui $a0, 0x40
.text:004006CC la $t9, __isoc99_scanf
.text:004006D0 la $a0, aD # "%d"
.text:004006D4 jalr $t9 ; __isoc99_scanf
.text:004006D8 addiu $a1, $sp, 0x28+var_10 # branch delay slot
.text:004006DC li $v1, 1
.text:004006E0 lw $gp, 0x28+var_18($sp)
.text:004006E4 beq $v0, $v1, loc_40070C
.text:004006E8 or $at, $zero # branch delay slot, NOP
.text:004006EC la $t9, puts
.text:004006F0 lui $a0, 0x40
.text:004006F4 jalr $t9 ; puts
.text:004006F8 la $a0, aWhatYouEntered # "What you entered? Huh?"
.text:004006FC lw $ra, 0x28+var_4($sp)
.text:00400700 move $v0, $zero
.text:00400704 jr $ra
.text:00400708 addiu $sp, 0x28

.text:0040070C loc_40070C:
.text:0040070C la $t9, printf
.text:00400710 lw $a1, 0x28+var_10($sp)
.text:00400714 lui $a0, 0x40
.text:00400718 jalr $t9 ; printf
.text:0040071C la $a0, aYouEnteredD___ # "You entered %d...\n"
.text:00400720 lw $ra, 0x28+var_4($sp)
.text:00400724 move $v0, $zero
.text:00400728 jr $ra
.text:0040072C addiu $sp, 0x28

scanf() $V0 0x004006E4 -


$V0 $V1 (1 $V1 , 0x004006DC). BEQ Branch Equal ( ).
(.. ), 0x0040070C.

7.3.8.

, JNE/JNZ JE/JZ ( BNE BEQ ).


. - .

7.4.

7.4.1. #1

, GCC Linux x86-64, (segmentation fault).


Windows, MSVC 2010 x86. ?
#include <string.h>
#include <stdio.h>

void alter_string(char *s)


{
strcpy (s, "Goodbye!");
printf ("Result: %s\n", s);
};

int main()
{
alter_string ("Hello, world!\n");
};

: G.1.3 (. 986).

90
8. 8.

, .
?

8.1:
#include <stdio.h>

int f (int a, int b, int c)


{
return a*b+c;
};

int main()
{
printf ("%d\n", f(1, 2, 3));
return 0;
};

8.1. x86

8.1.1. MSVC

, (MSVC 2010 Express):

8.2: MSVC 2010 Express


_TEXT SEGMENT
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_c$ = 16 ; size = 4
_f PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _a$[ebp]
imul eax, DWORD PTR _b$[ebp]
add eax, DWORD PTR _c$[ebp]
pop ebp
ret 0
_f ENDP

_main PROC
push ebp
mov ebp, esp
push 3 ;
push 2 ;
push 1 ;
call _f
add esp, 12
push eax
push OFFSET $SG2463 ; '%d', 0aH, 00H

91
8. 8.
call _printf
add esp, 8
; 0
xor eax, eax
pop ebp
ret 0
_main ENDP

, : main() f(int,int,int).
f() , , : _a$ = 8, ,
, _a$ EBP,
EBP.
- : a EAX. EAX IMUL
, _b, EAX . EAX ,
_c. EAX , .
EAX printf().

8.1.2. MSVC + OllyDbg

OllyDbg. f(), -
(), , EBP . .
EBP, RA. ,
. EBP 8 (2 32-
).
OllyDbg , RETURN from Arg1 = , ..
N.B.: , . OllyDbg
Arg .

. 8.1: OllyDbg: f()

8.1.3. GCC

GCC 4.4.1 IDA:

8.3: GCC 4.4.1


public f
f proc near

arg_0 = dword ptr 8


arg_4 = dword ptr 0Ch
arg_8 = dword ptr 10h

push ebp

92
8. 8.
mov ebp, esp
mov eax, [ebp+arg_0] ;
imul eax, [ebp+arg_4] ;
add eax, [ebp+arg_8] ;
pop ebp
retn
f endp

public main
main proc near

var_10 = dword ptr 10h


var_C = dword ptr 0Ch
var_8 = dword ptr 8

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 10h
mov [esp+10h+var_8], 3 ;
mov [esp+10h+var_C], 2 ;
mov [esp+10h+var_10], 1 ;
call f
mov edx, offset aD ; "%d\n"
mov [esp+10h+var_C], eax
mov [esp+10h+var_10], edx
call _printf
mov eax, 0
leave
retn
main endp

, .
, LEAVE
(A.6.2 (. 965)) , .

8.2. x64
x86-64 , (4 6) , callee
, .

8.2.1. MSVC

MSVC:

8.4: MSVC 2012 x64


$SG2997 DB '%d', 0aH, 00H

main PROC
sub rsp, 40
mov edx, 2
lea r8d, QWORD PTR [rdx+1] ; R8D=3
lea ecx, QWORD PTR [rdx1] ; ECX=1
call f
lea rcx, OFFSET FLAT:$SG2997 ; '%d'
mov edx, eax
call printf
xor eax, eax
add rsp, 40
ret 0
main ENDP

f PROC
; ECX
; EDX

93
8. 8.
; R8D
imul ecx, edx
lea eax, DWORD PTR [r8+rcx]
ret 0
f ENDP

, f() . LEA
. , ADD. main()
LEA : , , LEA
, MOV.
MSVC:

8.5: MSVC 2012 x64


f proc near

; shadow space:
arg_0 = dword ptr 8
arg_8 = dword ptr 10h
arg_10 = dword ptr 18h

; ECX
; EDX
; R8D
mov [rsp+arg_10], r8d
mov [rsp+arg_8], edx
mov [rsp+arg_0], ecx
mov eax, [rsp+arg_0]
imul eax, [rsp+arg_8]
add eax, [rsp+arg_10]
retn
f endp

main proc near


sub rsp, 28h
mov r8d, 3 ;
mov edx, 2 ;
mov ecx, 1 ;
call f
mov edx, eax
lea rcx, $SG2931 ; "%d\n"
call printf

; 0
xor eax, eax
add rsp, 28h
retn
main endp

: 3 - . shadow space 1 :
Win64 ( ) 4- . -
: 1) ( 4 )
, ; 2) ,
2 .
, - shadows space ,
, , .
shadow space caller.

8.2.2. GCC

GCC :

8.6: GCC 4.4.6 x64

1 MSDN
2 MSDN

94
8. 8.
f:
; EDI
; ESI
; EDX
imul esi, edi
lea eax, [rdx+rsi]
ret

main:
sub rsp, 8
mov edx, 3
mov esi, 2
mov edi, 1
call f
mov edi, OFFSET FLAT:.LC0 ; "%d\n"
mov esi, eax
xor eax, eax ;
call printf
xor eax, eax
add rsp, 8
ret

GCC:

8.7: GCC 4.4.6 x64


f:
; EDI
; ESI
; EDX
push rbp
mov rbp, rsp
mov DWORD PTR [rbp4], edi
mov DWORD PTR [rbp8], esi
mov DWORD PTR [rbp12], edx
mov eax, DWORD PTR [rbp4]
imul eax, DWORD PTR [rbp8]
add eax, DWORD PTR [rbp12]
leave
ret
main:
push rbp
mov rbp, rsp
mov edx, 3
mov esi, 2
mov edi, 1
call f
mov edx, eax
mov eax, OFFSET FLAT:.LC0 ; "%d\n"
mov esi, edx
mov rdi, rax
mov eax, 0 ;
call printf
mov eax, 0
leave
ret

System V *NIX[Mit13] shadow space, callee - -


, , , . .

8.2.3. GCC: uint64_t int

32- int, 32- E-.


, 64- :
#include <stdio.h>
#include <stdint.h>

95
8. 8.
uint64_t f (uint64_t a, uint64_t b, uint64_t c)
{
return a*b+c;
};

int main()
{
printf ("%lld\n", f(0x1122334455667788,
0x1111111122222222,
0x3333333344444444));
return 0;
};

8.8: GCC 4.4.6 x64


f proc near
imul rsi, rdi
lea rax, [rdx+rsi]
retn
f endp

main proc near


sub rsp, 8
mov rdx, 3333333344444444h ;
mov rsi, 1111111122222222h ;
mov rdi, 1122334455667788h ;
call f
mov edi, offset format ; "%lld\n"
mov rsi, rax
xor eax, eax ;
call _printf
xor eax, eax
add rsp, 8
retn
main endp

, , , R-.

8.3. ARM

8.3.1. Keil 6/2013 ( ARM)

.text:000000A4 00 30 A0 E1 MOV R3, R0


.text:000000A8 93 21 20 E0 MLA R0, R3, R1, R2
.text:000000AC 1E FF 2F E1 BX LR
...
.text:000000B0 main
.text:000000B0 10 40 2D E9 STMFD SP!, {R4,LR}
.text:000000B4 03 20 A0 E3 MOV R2, #3
.text:000000B8 02 10 A0 E3 MOV R1, #2
.text:000000BC 01 00 A0 E3 MOV R0, #1
.text:000000C0 F7 FF FF EB BL f
.text:000000C4 00 40 A0 E1 MOV R4, R0
.text:000000C8 04 10 A0 E1 MOV R1, R4
.text:000000CC 5A 0F 8F E2 ADR R0, aD_0 ; "%d\n"
.text:000000D0 E3 18 00 EB BL __2printf
.text:000000D4 00 00 A0 E3 MOV R0, #0
.text:000000D8 10 80 BD E8 LDMFD SP!, {R4,PC}

main() , (f()) .
, 4 ARM 4- (R0-R3).
f(), , (R0-R2) .
MLA (Multiply Accumulate) (R3 R1), -
(R2) (R0), , ,
.

96
8. 8.
3 (Fused multiplyadd) . , -
x86 FMA- SIMD4 .
MOV R3, R0, -, (
MLA). , , .
BX , LR , ,
Thumb ARM . , , , f() ,
, ARM Thumb. , Thumb, BX
, Thumb.
, ARM: [ARM12, A2.3.2].

8.3.2. Keil 6/2013 ( ARM)

.text:00000098 f
.text:00000098 91 20 20 E0 MLA R0, R1, R0, R2
.text:0000009C 1E FF 2F E1 BX LR

f(), Keil (-O3). MOV


: MLA R0,
.

8.3.3. Keil 6/2013 ( Thumb)

.text:0000005E 48 43 MULS R0, R1


.text:00000060 80 18 ADDS R0, R0, R2
.text:00000062 70 47 BX LR

Thumb MLA , , -
. MULS R0 R1, R1. (ADDS)
R2, R0.

8.3.4. ARM64

GCC (Linaro) 4.9

. MADD , ( MLA,
). 3 32- X-. ,
32- int. W0.

8.9: GCC (Linaro) 4.9


f:
madd w0, w0, w1, w2
ret

main:
; FP LR :
stp x29, x30, [sp, 16]!
mov w2, 3
mov w1, 2
add x29, sp, 0
mov w0, 1
bl f
mov w1, w0
adrp x0, .LC7
add x0, x0, :lo12:.LC7
bl printf
; 0
mov w0, 0
; FP LR
ldp x29, x30, [sp], 16
3 Wikipedia: -
4 wikipedia

97
8. 8.
ret

.LC7:
.string "%d\n"

64- uint64_t :
#include <stdio.h>
#include <stdint.h>

uint64_t f (uint64_t a, uint64_t b, uint64_t c)


{
return a*b+c;
};

int main()
{
printf ("%lld\n", f(0x1122334455667788,
0x1111111122222222,
0x3333333344444444));
return 0;
};

f:
madd x0, x0, x1, x2
ret
main:
mov x1, 13396
adrp x0, .LC8
stp x29, x30, [sp, 16]!
movk x1, 0x27d0, lsl 16
add x0, x0, :lo12:.LC8
movk x1, 0x122, lsl 32
add x29, sp, 0
movk x1, 0x58be, lsl 48
bl printf
mov w0, 0
ldp x29, x30, [sp], 16
ret

.LC8:
.string "%lld\n"

f() , 64- X-. 64-


, : 28.3.1 (. 465).

GCC (Linaro) 4.9

:
f:
sub sp, sp, #16
str w0, [sp,12]
str w1, [sp,8]
str w2, [sp,4]
ldr w1, [sp,12]
ldr w0, [sp,8]
mul w1, w1, w0
ldr w0, [sp,4]
add w0, w1, w0
add sp, sp, 16
ret

- ( -)
W0...W2, , -
. Register Save Area. [ARM13c] . Shadow
Space: 8.2.1 (. 94).

98
8. 8.
GCC 4.9 , , ?
, W0...W2
.
MUL/ ADD MADD.

8.4. MIPS

8.10: GCC 4.4.5


.text:00000000 f:
; $a0=a
; $a1=b
; $a2=c
.text:00000000 mult $a1, $a0
.text:00000004 mflo $v0
.text:00000008 jr $ra
.text:0000000C addu $v0, $a2, $v0 ; branch delay slot
; $v0

.text:00000010 main:
.text:00000010
.text:00000010 var_10 = 0x10
.text:00000010 var_4 = 4
.text:00000010
.text:00000010 lui $gp, (__gnu_local_gp >> 16)
.text:00000014 addiu $sp, 0x20
.text:00000018 la $gp, (__gnu_local_gp & 0xFFFF)
.text:0000001C sw $ra, 0x20+var_4($sp)
.text:00000020 sw $gp, 0x20+var_10($sp)
; c:
.text:00000024 li $a2, 3
; a:
.text:00000028 li $a0, 1
.text:0000002C jal f
; b:
.text:00000030 li $a1, 2 ; branch delay slot
; $v0
.text:00000034 lw $gp, 0x20+var_10($sp)
.text:00000038 lui $a0, ($LC0 >> 16)
.text:0000003C lw $t9, (printf & 0xFFFF)($gp)
.text:00000040 la $a0, ($LC0 & 0xFFFF)
.text:00000044 jalr $t9
; - f() printf():
.text:00000048 move $a1, $v0 ; branch delay slot
.text:0000004C lw $ra, 0x20+var_4($sp)
.text:00000050 move $v0, $zero
.text:00000054 jr $ra
.text:00000058 addiu $sp, 0x20 ; branch delay slot

4 A-.
MIPS : HI LO, 64- -
MULT. MFLO MFHI. MFLO
$V0. 32-
( HI ). , 32- int.
, ADDU (Add Unsigned ) .
MIPS : ADD ADDU. , , :
ADD . 5 , , Ada.
ADDU . /++ ,
ADDU ADD.
32- $V0.
main() : JAL (Jump and Link). JAL JALR ,
, JALR , (Jump
5 http://go.yurichev.com/17326

99
8. 8.
and Link Register). f() main() ,
f() .

100
9. 9.

x86 1 EAX,
(char), EAX AL. ,
FPU ST(0). ARM R0.

9.1. void
, , main() int, void?
.. startup- main() :
push envp
push argv
push argc
call main
push eax
call exit

:
exit(main(argc,argv,envp));

main() void, ( return), -


exit() , EAX main(). , , -
, . .

. , main() void:
#include <stdio.h>

void main()
{
printf ("Hello, world!\n");
};

Linux.
GCC 4.8.1 printf() puts() ( : 3.4.3 (. 15)) , , puts()
, printf(). , EAX
main(). EAX main() , puts() .

9.1: GCC 4.8.1


.LC0:
.string "Hello, world!"
main:
push ebp
mov ebp, esp
and esp, 16
sub esp, 16
1 . : MSDN: Return Values (C++): MSDN

101
9. 9.
mov DWORD PTR [esp], OFFSET FLAT:.LC0
call puts
leave
ret

bash, (exit status exit code) :

9.2: tst.sh
#!/bin/sh
./hello_world
echo $?

:
$ tst.sh
Hello, world!
14

14 .

9.2. ?
printf() , -
. , ,
:
int f()
{
// skip first 3 random values
rand();
rand();
rand();
// and use 4th
return rand();
};

rand() EAX . , EAX,


.

9.3.
, EAX.
, , ( int),
, , . ,
, , .
, , , , .
, , ,
. ,
.
:
struct s
{
int a;
int b;
int c;
};

struct s get_some_values (int a)


{
struct s rt;

rt.a=a+1;

102
9. 9.
rt.b=a+2;
rt.c=a+3;

return rt;
};

(MSVC 2010 /Ox):


$T3853 = 8 ; size = 4
_a$ = 12 ; size = 4
?get_some_values@@YA?AUs@@H@Z PROC ; get_some_values
mov ecx, DWORD PTR _a$[esp4]
mov eax, DWORD PTR $T3853[esp4]
lea edx, DWORD PTR [ecx+1]
mov DWORD PTR [eax], edx
lea edx, DWORD PTR [ecx+2]
add ecx, 3
mov DWORD PTR [eax+4], edx
mov DWORD PTR [eax+8], ecx
ret 0
?get_some_values@@YA?AUs@@H@Z ENDP ; get_some_values

$T3853 .
, C99:
struct s
{
int a;
int b;
int c;
};

struct s get_some_values (int a)


{
return (struct s){.a=a+1, .b=a+2, .c=a+3};
};

9.3: GCC 4.8.1


_get_some_values proc near

ptr_to_struct = dword ptr 4


a = dword ptr 8

mov edx, [esp+a]


mov eax, [esp+ptr_to_struct]
lea ecx, [edx+1]
mov [eax], ecx
lea ecx, [edx+2]
add edx, 3
mov [eax+4], ecx
mov [eax+8], edx
retn
_get_some_values endp

, , .
. .

103
10. 10.

10

( scanf() (7 (. 61))).
, .

10.1.

#include <stdio.h>

void f1 (int x, int y, int *sum, int *product)


{
*sum=x+y;
*product=x*y;
};

int sum, product;

void main()
{
f1(123, 456, &sum, &product);
printf ("sum=%d, product=%d\n", sum, product);
};

10.1: MSVC 2010 (/Ob0)


COMM _product:DWORD
COMM _sum:DWORD
$SG2803 DB 'sum=%d, product=%d', 0aH, 00H

_x$ = 8 ; size = 4
_y$ = 12 ; size = 4
_sum$ = 16 ; size = 4
_product$ = 20 ; size = 4
_f1 PROC
mov ecx, DWORD PTR _y$[esp4]
mov eax, DWORD PTR _x$[esp4]
lea edx, DWORD PTR [eax+ecx]
imul eax, ecx
mov ecx, DWORD PTR _product$[esp4]
push esi
mov esi, DWORD PTR _sum$[esp]
mov DWORD PTR [esi], edx
mov DWORD PTR [ecx], eax
pop esi
ret 0
_f1 ENDP

_main PROC
push OFFSET _product
push OFFSET _sum
push 456 ; 000001c8H

104
10. 10.
push 123 ; 0000007bH
call _f1
mov eax, DWORD PTR _product
mov ecx, DWORD PTR _sum
push eax
push ecx
push OFFSET $SG2803
call DWORD PTR __imp__printf
add esp, 28 ; 0000001cH
xor eax, eax
ret 0
_main ENDP

105
10. 10.
OllyDbg:

. 10.1: OllyDbg: f1()

f1(). Follow in dump


, . ,
(BSS) : [ISO07, 6.7.8p10].

106
10. 10.
, , Alt-M :

. 10.2: OllyDbg:

107
10. 10.
(F7) f1():

. 10.3: OllyDbg: f1()

456 (0x1C8) 123 (0x7B), .

108
10. 10.
f1(). , :

. 10.4: OllyDbg: f1()

109
10. 10.
printf():

. 10.5: OllyDbg: printf()

10.2.
:

10.2:
void main()
{
int sum, product; // -

f1(123, 456, &sum, &product);


printf ("sum=%d, product=%d\n", sum, product);
};

f1() . main():

10.3: MSVC 2010 (/Ob0)


_product$ = 8 ; size = 4
_sum$ = 4 ; size = 4
_main PROC
; Line 10
sub esp, 8
; Line 13
lea eax, DWORD PTR _product$[esp+8]
push eax
lea ecx, DWORD PTR _sum$[esp+12]
push ecx
push 456 ; 000001c8H
push 123 ; 0000007bH
call _f1
; Line 14
mov edx, DWORD PTR _product$[esp+24]
mov eax, DWORD PTR _sum$[esp+24]
push edx
push eax
push OFFSET $SG2803
call DWORD PTR __imp__printf
; Line 15
xor eax, eax
add esp, 36 ; 00000024H
ret 0

110
10. 10.
OllyDbg. 0x2EF854 0x2EF858. , -
:

. 10.6: OllyDbg:

111
10. 10.
f1(). 0x2EF854 0x2EF858 :

. 10.7: OllyDbg: f1()

112
10. 10.
f1():

. 10.8: OllyDbg: f1()

0x2EF854 0x2EF858 0xDB18 0x243, f1().

10.3.
f1() . .
, references ++ . : (51.3 (. 580)).

113
11. GOTO 11. GOTO

11

GOTO

GOTO - [Dij68], ,
[Knu74], [Yur13, . 1.3.2].
:
#include <stdio.h>

int main()
{
printf ("begin\n");
goto exit;
printf ("skip me!\n");
exit:
printf ("end\n");
};

MSVC 2012:

11.1: MSVC 2012


$SG2934 DB 'begin', 0aH, 00H
$SG2936 DB 'skip me!', 0aH, 00H
$SG2937 DB 'end', 0aH, 00H

_main PROC
push ebp
mov ebp, esp
push OFFSET $SG2934 ; 'begin'
call _printf
add esp, 4
jmp SHORT $exit$3
push OFFSET $SG2936 ; 'skip me!'
call _printf
add esp, 4
$exit$3:
push OFFSET $SG2937 ; 'end'
call _printf
add esp, 4
xor eax, eax
pop ebp
ret 0
_main ENDP

goto JMP, : .
printf() ,
.

114
11. GOTO 11. GOTO
. Hiew:

. 11.1: Hiew

115
11. GOTO 11. GOTO
JMP (0x410), F3 (), , EB
00:

. 11.2: Hiew

JMP . 0 .
JMP printf().
F9 () . :

. 11.3:

, JMP NOP. NOP 0x90


1 , 2 .

11.1.
printf() (dead code) . ,
. ,
:

11.2: MSVC 2012


$SG2981 DB 'begin', 0aH, 00H
$SG2983 DB 'skip me!', 0aH, 00H
$SG2984 DB 'end', 0aH, 00H

_main PROC
push OFFSET $SG2981 ; 'begin'
call _printf
push OFFSET $SG2984 ; 'end'
$exit$4:
call _printf
add esp, 8
xor eax, eax
ret 0
_main ENDP

, skip me! .

116
11. GOTO 11. GOTO
11.2.
.

117
12. 12.

12

12.1.

#include <stdio.h>

void f_signed (int a, int b)


{
if (a>b)
printf ("a>b\n");
if (a==b)
printf ("a==b\n");
if (a<b)
printf ("a<b\n");
};

void f_unsigned (unsigned int a, unsigned int b)


{
if (a>b)
printf ("a>b\n");
if (a==b)
printf ("a==b\n");
if (a<b)
printf ("a<b\n");
};

int main()
{
f_signed(1, 2);
f_unsigned(1, 2);
return 0;
};

12.1.1. x86

x86 + MSVC

f_signed():

12.1: MSVC 2010


_a$ = 8
_b$ = 12
_f_signed PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _a$[ebp]
cmp eax, DWORD PTR _b$[ebp]
jle SHORT $LN3@f_signed
push OFFSET $SG737 ; 'a>b'
call _printf
add esp, 4

118
12. 12.
$LN3@f_signed:
mov ecx, DWORD PTR _a$[ebp]
cmp ecx, DWORD PTR _b$[ebp]
jne SHORT $LN2@f_signed
push OFFSET $SG739 ; 'a==b'
call _printf
add esp, 4
$LN2@f_signed:
mov edx, DWORD PTR _a$[ebp]
cmp edx, DWORD PTR _b$[ebp]
jge SHORT $LN4@f_signed
push OFFSET $SG741 ; 'a<b'
call _printf
add esp, 4
$LN4@f_signed:
pop ebp
ret 0
_f_signed ENDP

JLE Jump if Less or Equal. ,


, . (
), , printf(). JNE: Jump if Not Equal.
, .
JGE: Jump if Greater or Equal . -
, , printf() .
.
f_unsigned() , , JBE JAE JLE JGE:

12.2: GCC
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_f_unsigned PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _a$[ebp]
cmp eax, DWORD PTR _b$[ebp]
jbe SHORT $LN3@f_unsigned
push OFFSET $SG2761 ; 'a>b'
call _printf
add esp, 4
$LN3@f_unsigned:
mov ecx, DWORD PTR _a$[ebp]
cmp ecx, DWORD PTR _b$[ebp]
jne SHORT $LN2@f_unsigned
push OFFSET $SG2763 ; 'a==b'
call _printf
add esp, 4
$LN2@f_unsigned:
mov edx, DWORD PTR _a$[ebp]
cmp edx, DWORD PTR _b$[ebp]
jae SHORT $LN4@f_unsigned
push OFFSET $SG2765 ; 'a<b'
call _printf
add esp, 4
$LN4@f_unsigned:
pop ebp
ret 0
_f_unsigned ENDP

, : JBE Jump if Below or Equal JAE


Jump if Above or Equal. (JA/ JAE/ JBE/ JBE) JG/ JGE/ JL/ JLE ,
.
: (30 (. 471)). , -
JG/ JL JA/ JBE , ,
(signed) (unsigned).
main(), :

119
12. 12.
12.3: main()
_main PROC
push ebp
mov ebp, esp
push 2
push 1
call _f_signed
add esp, 8
push 2
push 1
call _f_unsigned
add esp, 8
xor eax, eax
pop ebp
ret 0
_main ENDP

120
12. 12.
x86 + MSVC + OllyDbg

OllyDbg, , . f_unsigned(),
. CMP ,
, .
:

. 12.1: OllyDbg: f_unsigned():

, : C=1, P=1, A=1, Z=0, S=1, T=0, D=0, O=0. , OllyDbg .


OllyDbg , (JBE) . , [Int13],
, JBE CF=1 ZF=1. , .

121
12. 12.
:

. 12.2: OllyDbg: f_unsigned():

OllyDbg , JNZ . , JNZ ZF=0 (zero ag).

122
12. 12.
, JNB:

. 12.3: OllyDbg: f_unsigned():

[Int13] , JNB CF=0 (carry ag). , ,


printf().

123
12. 12.
OllyDbg f_signed(), .
: C=1, P=1, A=1, Z=0, S=1, T=0, D=0, O=0.
JLE :

. 12.4: OllyDbg: f_signed():

[Int13] , ZF=1 SFOF. SFOF,


.

124
12. 12.
JNZ : ZF=0 (zero ag):

. 12.5: OllyDbg: f_signed():

125
12. 12.
JGE , , SF=OF, :

. 12.6: OllyDbg: f_signed():

126
12. 12.
x86 + MSVC + Hiew

, f_unsigned() a==b,
. Hiew:

. 12.7: Hiew: f_unsigned()

, :
;
;
.
(code ow) printf(),
a==b.
( ):
JMP, (jump offset) .
,
, (jump offset) 0.
. 0,
.
JMP , , .

127
12. 12.
:

. 12.8: Hiew: f_unsigned()

- , printf(),
.

GCC

GCC 4.4.1 , puts() (3.4.3 (. 15)) printf().

GCC

, CMP , ?
, MSVC , GCC 4.8.1 :

12.4: GCC 4.8.1 f_signed()


f_signed:
mov eax, DWORD PTR [esp+8]
cmp DWORD PTR [esp+4], eax
jg .L6
je .L7
jge .L1
mov DWORD PTR [esp+4], OFFSET FLAT:.LC2 ; "a<b"
jmp puts
.L6:
mov DWORD PTR [esp+4], OFFSET FLAT:.LC0 ; "a>b"
jmp puts
.L1:
rep ret
.L7:

128
12. 12.
mov DWORD PTR [esp+4], OFFSET FLAT:.LC1 ; "a==b"
jmp puts

JMP puts CALL puts / RETN. : 13.1.1 (. 148).


, x86- . MSVC 2012, , . ,
, Jcc .
-, , .
f_unsigned() :

12.5: GCC 4.8.1 f_unsigned()


f_unsigned:
push esi
push ebx
sub esp, 20
mov esi, DWORD PTR [esp+32]
mov ebx, DWORD PTR [esp+36]
cmp esi, ebx
ja .L13
cmp esi, ebx ;
je .L14
.L10:
jb .L15
add esp, 20
pop ebx
pop esi
ret
.L15:
mov DWORD PTR [esp+32], OFFSET FLAT:.LC2 ; "a<b"
add esp, 20
pop ebx
pop esi
jmp puts
.L13:
mov DWORD PTR [esp], OFFSET FLAT:.LC0 ; "a>b"
call puts
cmp esi, ebx
jne .L10
.L14:
mov DWORD PTR [esp+32], OFFSET FLAT:.LC1 ; "a==b"
add esp, 20
pop ebx
pop esi
jmp puts

, 2 CMP . , GCC 4.8.1, ,


.

12.1.2. ARM

32- ARM

Keil 6/2013 ( ARM)

12.6: Keil 6/2013 ( ARM)


.text:000000B8 EXPORT f_signed
.text:000000B8 f_signed ; CODE XREF: main+C
.text:000000B8 70 40 2D E9 STMFD SP!, {R4R6,LR}
.text:000000BC 01 40 A0 E1 MOV R4, R1
.text:000000C0 04 00 50 E1 CMP R0, R4
.text:000000C4 00 50 A0 E1 MOV R5, R0
.text:000000C8 1A 0E 8F C2 ADRGT R0, aAB ; "a>b\n"
.text:000000CC A1 18 00 CB BLGT __2printf
.text:000000D0 04 00 55 E1 CMP R5, R4
.text:000000D4 67 0F 8F 02 ADREQ R0, aAB_0 ; "a==b\n"
.text:000000D8 9E 18 00 0B BLEQ __2printf

129
12. 12.
.text:000000DC 04 00 55 E1 CMP R5, R4
.text:000000E0 70 80 BD A8 LDMGEFD SP!, {R4R6,PC}
.text:000000E4 70 40 BD E8 LDMFD SP!, {R4R6,LR}
.text:000000E8 19 0E 8F E2 ADR R0, aAB_1 ; "a<b\n"
.text:000000EC 99 18 00 EA B __2printf
.text:000000EC ; End of function f_signed

ARM .
.
, ADD ADDAL , AL Always, , .
4- 32- ARM- (condition eld). -
B , ,
AL condition eld, (execute ALways), .
ADRGT , ADR, , CMP, -
, , (Greater Than).
BLGT , BL ,
(Greater Than). ADRGT R0 a>b\n , BLGT printf(). , -
-GT , R0 ( a) , R4
( b).
ADREQ BLEQ. , ADR BL, -
. CMP, printf()
.
LDMGEFD. , LDMFD1 , -
(Greater or Equal).
LDMGEFD SP!, {R4-R6,PC} , , a >= b,
.
, a < b, LDMFD SP!, {R4-R6,LR}.
. R4-R6, LR PC, ,
, .
printf() a<b\n .
printf() printf() -
(6.2.1 (. 48)).
f_unsigned , ADRHI, BLHI, LDMCSFD. (HI =
Unsigned higher, CS = Carry Set (greater than or equal)) ,
.
main() :

12.7: main()
.text:00000128 EXPORT main
.text:00000128 main
.text:00000128 10 40 2D E9 STMFD SP!, {R4,LR}
.text:0000012C 02 10 A0 E3 MOV R1, #2
.text:00000130 01 00 A0 E3 MOV R0, #1
.text:00000134 DF FF FF EB BL f_signed
.text:00000138 02 10 A0 E3 MOV R1, #2
.text:0000013C 01 00 A0 E3 MOV R0, #1
.text:00000140 EA FF FF EB BL f_unsigned
.text:00000144 00 00 A0 E3 MOV R0, #0
.text:00000148 10 80 BD E8 LDMFD SP!, {R4,PC}
.text:00000148 ; End of function main

, ARM .
? : 33.1 (. 476).
x86 , CMOVcc, MOV,
, CMP .
1 LDMFD

130
12. 12.
Keil 6/2013 ( Thumb)

12.8: Keil 6/2013 ( Thumb)


.text:00000072 f_signed ; CODE XREF: main+6
.text:00000072 70 B5 PUSH {R4R6,LR}
.text:00000074 0C 00 MOVS R4, R1
.text:00000076 05 00 MOVS R5, R0
.text:00000078 A0 42 CMP R0, R4
.text:0000007A 02 DD BLE loc_82
.text:0000007C A4 A0 ADR R0, aAB ; "a>b\n"
.text:0000007E 06 F0 B7 F8 BL __2printf
.text:00000082
.text:00000082 loc_82 ; CODE XREF: f_signed+8
.text:00000082 A5 42 CMP R5, R4
.text:00000084 02 D1 BNE loc_8C
.text:00000086 A4 A0 ADR R0, aAB_0 ; "a==b\n"
.text:00000088 06 F0 B2 F8 BL __2printf
.text:0000008C
.text:0000008C loc_8C ; CODE XREF: f_signed+12
.text:0000008C A5 42 CMP R5, R4
.text:0000008E 02 DA BGE locret_96
.text:00000090 A3 A0 ADR R0, aAB_1 ; "a<b\n"
.text:00000092 06 F0 AD F8 BL __2printf
.text:00000096
.text:00000096 locret_96 ; CODE XREF: f_signed+1C
.text:00000096 70 BD POP {R4R6,PC}
.text:00000096 ; End of function f_signed

Thumb B (condition code),


Thumb .
BLE Less than or Equal, BNE Not Equal, BGE Greater than or Equal.
f_unsigned , BLS
(Unsigned lower or same) BCS (Carry Set (Greater than or equal)).

ARM64: GCC (Linaro) 4.9

12.9: f_signed()
f_signed:
; W0=a, W1=b
cmp w0, w1
bgt .L19 ; Branch if Greater Than (, )(a>b)
beq .L20 ; Branch if Equal (, )(a==b)
bge .L15 ; Branch if Greater than or Equal (, )(a>=b) (
)
; a<b
adrp x0, .LC11 ; "a<b"
add x0, x0, :lo12:.LC11
b puts
.L19:
adrp x0, .LC9 ; "a>b"
add x0, x0, :lo12:.LC9
b puts
.L15: ;
ret
.L20:
adrp x0, .LC10 ; "a==b"
add x0, x0, :lo12:.LC10
b puts

12.10: f_unsigned()
f_unsigned:
stp x29, x30, [sp, 48]!
; W0=a, W1=b
cmp w0, w1

131
12. 12.
add x29, sp, 0
str x19, [sp,16]
mov w19, w0
bhi .L25 ; Branch if HIgher (, )(a>b)
cmp w19, w1
beq .L26 ; Branch if Equal (, )(a==b)
.L23:
bcc .L27 ; Branch if Carry Clear ( )( , ) (a<b)
; ,
ldr x19, [sp,16]
ldp x29, x30, [sp], 48
ret
.L27:
ldr x19, [sp,16]
adrp x0, .LC11 ; "a<b"
ldp x29, x30, [sp], 48
add x0, x0, :lo12:.LC11
b puts
.L25:
adrp x0, .LC9 ; "a>b"
str x1, [x29,40]
add x0, x0, :lo12:.LC9
bl puts
ldr x1, [x29,40]
cmp w19, w1
bne .L23 ; Branch if Not Equal (, )
.L26:
ldr x19, [sp,16]
adrp x0, .LC10 ; "a==b"
ldp x29, x30, [sp], 48
add x0, x0, :lo12:.LC10
b puts

. , ,
, - , .

, .

12.1.3. MIPS

MIPS . ,
(data dependency).
, SETcc x86: SLT (Set on Less Than ,
) SLTU ( ). - 1 0
.
- , BEQ (Branch on Equal ) BNE
(Branch on Not Equal ) .
MIPS .
:

12.11: GCC 4.4.5 (IDA)


.text:00000000 f_signed: # CODE XREF: main+18
.text:00000000
.text:00000000 var_10 = 0x10
.text:00000000 var_8 = 8
.text:00000000 var_4 = 4
.text:00000000 arg_0 = 0
.text:00000000 arg_4 = 4
.text:00000000
.text:00000000 addiu $sp, 0x20
.text:00000004 sw $ra, 0x20+var_4($sp)
.text:00000008 sw $fp, 0x20+var_8($sp)

132
12. 12.
.text:0000000C move $fp, $sp
.text:00000010 la $gp, __gnu_local_gp
.text:00000018 sw $gp, 0x20+var_10($sp)
; :
.text:0000001C sw $a0, 0x20+arg_0($fp)
.text:00000020 sw $a1, 0x20+arg_4($fp)
; reload them.
.text:00000024 lw $v1, 0x20+arg_0($fp)
.text:00000028 lw $v0, 0x20+arg_4($fp)
; $v0=b
; $v1=a
.text:0000002C or $at, $zero ; NOP
; . , "slt $v0,$v0,$v1" .
; $v0 1, $v0<$v1 (b<a) 0 :
.text:00000030 slt $v0, $v1
; loc_5c, .
; . , "beq $v0,$zero,loc_5c" :
.text:00000034 beqz $v0, loc_5C
; "a>b"
.text:00000038 or $at, $zero ; branch delay slot, NOP
.text:0000003C lui $v0, (unk_230 >> 16) # "a>b"
.text:00000040 addiu $a0, $v0, (unk_230 & 0xFFFF) # "a>b"
.text:00000044 lw $v0, (puts & 0xFFFF)($gp)
.text:00000048 or $at, $zero ; NOP
.text:0000004C move $t9, $v0
.text:00000050 jalr $t9
.text:00000054 or $at, $zero ; branch delay slot, NOP
.text:00000058 lw $gp, 0x20+var_10($fp)
.text:0000005C
.text:0000005C loc_5C: # CODE XREF: f_signed+34
.text:0000005C lw $v1, 0x20+arg_0($fp)
.text:00000060 lw $v0, 0x20+arg_4($fp)
.text:00000064 or $at, $zero ; NOP
; a==b, loc_90, :
.text:00000068 bne $v1, $v0, loc_90
.text:0000006C or $at, $zero ; branch delay slot, NOP
; , "a==b" :
.text:00000070 lui $v0, (aAB >> 16) # "a==b"
.text:00000074 addiu $a0, $v0, (aAB & 0xFFFF) # "a==b"
.text:00000078 lw $v0, (puts & 0xFFFF)($gp)
.text:0000007C or $at, $zero ; NOP
.text:00000080 move $t9, $v0
.text:00000084 jalr $t9
.text:00000088 or $at, $zero ; branch delay slot, NOP
.text:0000008C lw $gp, 0x20+var_10($fp)
.text:00000090
.text:00000090 loc_90: # CODE XREF: f_signed+68
.text:00000090 lw $v1, 0x20+arg_0($fp)
.text:00000094 lw $v0, 0x20+arg_4($fp)
.text:00000098 or $at, $zero ; NOP
; $v1<$v0 (a<b), $v0 1, :
.text:0000009C slt $v0, $v1, $v0
; (.. $v0==0), loc_c8:
.text:000000A0 beqz $v0, loc_C8
.text:000000A4 or $at, $zero ; branch delay slot, NOP
; , "a<b"
.text:000000A8 lui $v0, (aAB_0 >> 16) # "a<b"
.text:000000AC addiu $a0, $v0, (aAB_0 & 0xFFFF) # "a<b"
.text:000000B0 lw $v0, (puts & 0xFFFF)($gp)
.text:000000B4 or $at, $zero ; NOP
.text:000000B8 move $t9, $v0
.text:000000BC jalr $t9
.text:000000C0 or $at, $zero ; branch delay slot, NOP
.text:000000C4 lw $gp, 0x20+var_10($fp)
.text:000000C8
; 3 , :
.text:000000C8 loc_C8: # CODE XREF: f_signed+A0
.text:000000C8 move $sp, $fp
.text:000000CC lw $ra, 0x20+var_4($sp)
.text:000000D0 lw $fp, 0x20+var_8($sp)

133
12. 12.
.text:000000D4 addiu $sp, 0x20
.text:000000D8 jr $ra
.text:000000DC or $at, $zero ; branch delay slot, NOP
.text:000000DC # End of function f_signed

SLT REG0, REG0, REG1 IDA SLT REG0, REG1. -


BEQZ (Branch if Equal to Zero ), , , BEQ REG, $ZERO,
LABEL.
, SLTU ( , U )
SLT:

12.12: GCC 4.4.5 (IDA)


.text:000000E0 f_unsigned: # CODE XREF: main+28
.text:000000E0
.text:000000E0 var_10 = 0x10
.text:000000E0 var_8 = 8
.text:000000E0 var_4 = 4
.text:000000E0 arg_0 = 0
.text:000000E0 arg_4 = 4
.text:000000E0
.text:000000E0 addiu $sp, 0x20
.text:000000E4 sw $ra, 0x20+var_4($sp)
.text:000000E8 sw $fp, 0x20+var_8($sp)
.text:000000EC move $fp, $sp
.text:000000F0 la $gp, __gnu_local_gp
.text:000000F8 sw $gp, 0x20+var_10($sp)
.text:000000FC sw $a0, 0x20+arg_0($fp)
.text:00000100 sw $a1, 0x20+arg_4($fp)
.text:00000104 lw $v1, 0x20+arg_0($fp)
.text:00000108 lw $v0, 0x20+arg_4($fp)
.text:0000010C or $at, $zero
.text:00000110 sltu $v0, $v1
.text:00000114 beqz $v0, loc_13C
.text:00000118 or $at, $zero
.text:0000011C lui $v0, (unk_230 >> 16)
.text:00000120 addiu $a0, $v0, (unk_230 & 0xFFFF)
.text:00000124 lw $v0, (puts & 0xFFFF)($gp)
.text:00000128 or $at, $zero
.text:0000012C move $t9, $v0
.text:00000130 jalr $t9
.text:00000134 or $at, $zero
.text:00000138 lw $gp, 0x20+var_10($fp)
.text:0000013C
.text:0000013C loc_13C: # CODE XREF: f_unsigned+34
.text:0000013C lw $v1, 0x20+arg_0($fp)
.text:00000140 lw $v0, 0x20+arg_4($fp)
.text:00000144 or $at, $zero
.text:00000148 bne $v1, $v0, loc_170
.text:0000014C or $at, $zero
.text:00000150 lui $v0, (aAB >> 16) # "a==b"
.text:00000154 addiu $a0, $v0, (aAB & 0xFFFF) # "a==b"
.text:00000158 lw $v0, (puts & 0xFFFF)($gp)
.text:0000015C or $at, $zero
.text:00000160 move $t9, $v0
.text:00000164 jalr $t9
.text:00000168 or $at, $zero
.text:0000016C lw $gp, 0x20+var_10($fp)
.text:00000170
.text:00000170 loc_170: # CODE XREF: f_unsigned+68
.text:00000170 lw $v1, 0x20+arg_0($fp)
.text:00000174 lw $v0, 0x20+arg_4($fp)
.text:00000178 or $at, $zero
.text:0000017C sltu $v0, $v1, $v0
.text:00000180 beqz $v0, loc_1A8
.text:00000184 or $at, $zero
.text:00000188 lui $v0, (aAB_0 >> 16) # "a<b"
.text:0000018C addiu $a0, $v0, (aAB_0 & 0xFFFF) # "a<b"
.text:00000190 lw $v0, (puts & 0xFFFF)($gp)
.text:00000194 or $at, $zero

134
12. 12.
.text:00000198 move $t9, $v0
.text:0000019C jalr $t9
.text:000001A0 or $at, $zero
.text:000001A4 lw $gp, 0x20+var_10($fp)
.text:000001A8
.text:000001A8 loc_1A8: # CODE XREF: f_unsigned+A0
.text:000001A8 move $sp, $fp
.text:000001AC lw $ra, 0x20+var_4($sp)
.text:000001B0 lw $fp, 0x20+var_8($sp)
.text:000001B4 addiu $sp, 0x20
.text:000001B8 jr $ra
.text:000001BC or $at, $zero
.text:000001BC # End of function f_unsigned

12.2.
:
int my_abs (int i)
{
if (i<0)
return i;
else
return i;
};

12.2.1. MSVC

12.13: MSVC 2012 x64


i$ = 8
my_abs PROC
; ECX = input
test ecx, ecx
;
; NEG
jns SHORT $LN2@my_abs
;
neg ecx
$LN2@my_abs:
; EAX:
mov eax, ecx
ret 0
my_abs ENDP

GCC 4.9 .

12.2.2. Keil 6/2013: Thumb

12.14: Keil 6/2013: Thumb


my_abs PROC
CMP r0,#0
; ?
; , RSBS
BGE |L0.6|
; 0 0:
RSBS r0,r0,#0
|L0.6|
BX lr
ENDP

135
12. 12.
ARM , Keil Reverse Subtract,
, , .

12.2.3. Keil 6/2013: ARM

ARM , Keil :

12.15: Keil 6/2013: ARM


my_abs PROC
CMP r0,#0
; "Reverse Subtract" , 0:
RSBLT r0,r0,#0
BX lr
ENDP

: 33.1 (. 476).

12.2.4. GCC 4.9 (ARM64)

ARM64 NEG :

12.16: GCC 4.9 (ARM64)


my_abs:
sub sp, sp, #16
str w0, [sp,12]
ldr w0, [sp,12]
; WZR
; ( )
cmp w0, wzr
bge .L2
ldr w0, [sp,12]
neg w0, w0
b .L3
.L2:
ldr w0, [sp,12]
.L3:
add sp, sp, 16
ret

12.2.5. MIPS

12.17: GCC 4.4.5 (IDA)


my_abs:
; $a0<0:
bltz $a0, locret_10
; ($a0) $v0:
move $v0, $a0
jr $ra
or $at, $zero ; branch delay slot, NOP
locret_10:
; $v0:
jr $ra
; . , "subu $v0,$zero,$a0" ($v0=0$a0)
negu $v0, $a0

: BLTZ (Branch if Less Than Zero). NEGU,


. U SUBU NEGU ,
.

12.2.6. ?

, : 45 (. 534).

136
12. 12.
12.3.
(ternary conditional operator) /++ :
expression ? expression : expression

:
const char* f (int a)
{
return a==10 ? "it is ten" : "it is not ten";
};

12.3.1. x86

, if/else
:

12.18: MSVC 2008


$SG746 DB 'it is ten', 00H
$SG747 DB 'it is not ten', 00H

tv65 = 4 ;
_a$ = 8
_f PROC
push ebp
mov ebp, esp
push ecx
; 10
cmp DWORD PTR _a$[ebp], 10
; $LN3@f
jne SHORT $LN3@f
; :
mov DWORD PTR tv65[ebp], OFFSET $SG746 ; 'it is ten'
;
jmp SHORT $LN4@f
$LN3@f:
; :
mov DWORD PTR tv65[ebp], OFFSET $SG747 ; 'it is not ten'
$LN4@f:
; . EAX.
mov eax, DWORD PTR tv65[ebp]
mov esp, ebp
pop ebp
ret 0
_f ENDP

12.19: MSVC 2008


$SG792 DB 'it is ten', 00H
$SG793 DB 'it is not ten', 00H

_a$ = 8 ; size = 4
_f PROC
; 10
cmp DWORD PTR _a$[esp4], 10
mov eax, OFFSET $SG792 ; 'it is ten'
; $LN4@f
je SHORT $LN4@f
mov eax, OFFSET $SG793 ; 'it is not ten'
$LN4@f:
ret 0
_f ENDP

137
12. 12.
12.20: MSVC 2012 x64
$SG1355 DB 'it is ten', 00H
$SG1356 DB 'it is not ten', 00H

a$ = 8
f PROC
;
lea rdx, OFFSET FLAT:$SG1355 ; 'it is ten'
lea rax, OFFSET FLAT:$SG1356 ; 'it is not ten'
; 10
cmp ecx, 10
; , RDX ("it is ten")
; , . "it is not ten" RAX.
cmove rax, rdx
ret 0
f ENDP

GCC 4.8 x86 CMOVcc, GCC 4.8 -


.

12.3.2. ARM

Keil ARM ADRcc, :


12.21: Keil 6/2013 ( ARM)
f PROC
; 10
CMP r0,#0xa
; EQual (), "it is ten" R0
ADREQ r0,|L0.16| ; "it is ten"
; Not Equal ( ), "it is not ten" R0
ADRNE r0,|L0.28| ; "it is not ten"
BX lr
ENDP

|L0.16|
DCB "it is ten",0
|L0.28|
DCB "it is not ten",0

ADREQ ADRNE .
Keil Thumb ,
, :
12.22: Keil 6/2013 ( Thumb)
f PROC
; 10
CMP r0,#0xa
; |L0.8| EQual ()
BEQ |L0.8|
ADR r0,|L0.12| ; "it is not ten"
BX lr
|L0.8|
ADR r0,|L0.28| ; "it is ten"
BX lr
ENDP

|L0.12|
DCB "it is not ten",0
|L0.28|
DCB "it is ten",0

12.3.3. ARM64

GCC (Linaro) 4.9 ARM64 :

138
12. 12.
12.23: GCC (Linaro) 4.9
f:
cmp x0, 10
beq .L3 ; branch if equal (, )
adrp x0, .LC1 ; "it is ten"
add x0, x0, :lo12:.LC1
ret
.L3:
adrp x0, .LC0 ; "it is not ten"
add x0, x0, :lo12:.LC0
ret
.LC0:
.string "it is ten"
.LC1:
.string "it is not ten"

ARM64 , ADRcc 32- ARM


CMOVcc x86 [ARM13a, p390, C5.5]. , CSEL (Conditional SELect), GCC 4.9
, , .

12.3.4. MIPS

GCC 4.4.5 MIPS , :

12.24: GCC 4.4.5 ( )


$LC0:
.ascii "it is not ten\000"
$LC1:
.ascii "it is ten\000"
f:
li $2,10 # 0xa
; $a0 10, , :
beq $4,$2,$L2
nop ; branch delay slot

; "it is not ten" $v0 :


lui $2,%hi($LC0)
j $31
addiu $2,$2,%lo($LC0)

$L2:
; "it is ten" $v0 :
lui $2,%hi($LC1)
j $31
addiu $2,$2,%lo($LC1)

12.3.5. , if/else

const char* f (int a)


{
if (a==10)
return "it is ten";
else
return "it is not ten";
};

, GCC 4.8 x86 CMOVcc :

12.25: GCC 4.8


.LC0:
.string "it is ten"
.LC1:
.string "it is not ten"
f:
.LFB0:

139
12. 12.
; 10
cmp DWORD PTR [esp+4], 10
mov edx, OFFSET FLAT:.LC1 ; "it is not ten"
mov eax, OFFSET FLAT:.LC0 ; "it is ten"
; Not Equal ( ), EDX EAX
; ,
cmovne eax, edx
ret

Keil ARM : .12.21.


MSVC 2012 .

12.3.6.

? :
33.1 (. 476).

12.4.

12.4.1. 32-bit

int my_max(int a, int b)


{
if (a>b)
return a;
else
return b;
};

int my_min(int a, int b)


{
if (a<b)
return a;
else
return b;
};

12.26: MSVC 2013


_a$ = 8
_b$ = 12
_my_min PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _a$[ebp]
; A B:
cmp eax, DWORD PTR _b$[ebp]
; , A B:
jge SHORT $LN2@my_min
; A EAX
mov eax, DWORD PTR _a$[ebp]
jmp SHORT $LN3@my_min
jmp SHORT $LN3@my_min ; JMP
$LN2@my_min:
; B
mov eax, DWORD PTR _b$[ebp]
$LN3@my_min:
pop ebp
ret 0
_my_min ENDP

_a$ = 8
_b$ = 12
_my_max PROC
push ebp

140
12. 12.
mov ebp, esp
mov eax, DWORD PTR _a$[ebp]
; A B:
cmp eax, DWORD PTR _b$[ebp]
; , A B:
jle SHORT $LN2@my_max
; A EAX
mov eax, DWORD PTR _a$[ebp]
jmp SHORT $LN3@my_max
jmp SHORT $LN3@my_max ; JMP
$LN2@my_max:
; B
mov eax, DWORD PTR _b$[ebp]
$LN3@my_max:
pop ebp
ret 0
_my_max ENDP

: JGE (Jump if Greater or Equal


) JLE (Jump if Less or Equal )
.
JMP , MSVC, , .

ARM Thumb x86-:

12.27: Keil 6/2013 ( Thumb)


my_max PROC
; R0=A
; R1=B
; A B:
CMP r0,r1
; , A B:
BGT |L0.6|
; (A<=B) R1 (B):
MOVS r0,r1
|L0.6|
;
BX lr
ENDP

my_min PROC
; R0=A
; R1=B
; A B:
CMP r0,r1
; , A B:
BLT |L0.14|
; (A>=B) R1 (B):
MOVS r0,r1
|L0.14|
;
BX lr
ENDP

: BGT BLT.
ARM , . MOVcc
:

12.28: Keil 6/2013 ( ARM)


my_max PROC
; R0=A
; R1=B
; A B:
CMP r0,r1

141
12. 12.
; B A B R0
; A<=B (.. LE - Less or Equal, )
; ( A>B), A R0
MOVLE r0,r1
BX lr
ENDP

my_min PROC
; R0=A
; R1=B
; A B:
CMP r0,r1
; B A B R0
; A>=B (.. GE - Greater or Equal, )
; ( A<B), A R0
MOVGE r0,r1
BX lr
ENDP

GCC 4.8.1 MSVC 2013 CMOVcc,


MOVcc ARM:

12.29: MSVC 2013


my_max:
mov edx, DWORD PTR [esp+4]
mov eax, DWORD PTR [esp+8]
; EDX=A
; EAX=B
; A B:
cmp edx, eax
; A>=B, A EAX
; , ( A<B)
cmovge eax, edx
ret

my_min:
mov edx, DWORD PTR [esp+4]
mov eax, DWORD PTR [esp+8]
; EDX=A
; EAX=B
; A B:
cmp edx, eax
; A<=B, A EAX
; , ( A>B)
cmovle eax, edx
ret

12.4.2. 64-bit

#include <stdint.h>

int64_t my_max(int64_t a, int64_t b)


{
if (a>b)
return a;
else
return b;
};

int64_t my_min(int64_t a, int64_t b)


{
if (a<b)
return a;
else
return b;
};

142
12. 12.
, :

12.30: GCC 4.9.1 ARM64


my_max:
sub sp, sp, #16
str x0, [sp,8]
str x1, [sp]
ldr x1, [sp,8]
ldr x0, [sp]
cmp x1, x0
ble .L2
ldr x0, [sp,8]
b .L3
.L2:
ldr x0, [sp]
.L3:
add sp, sp, 16
ret

my_min:
sub sp, sp, #16
str x0, [sp,8]
str x1, [sp]
ldr x1, [sp,8]
ldr x0, [sp]
cmp x1, x0
bge .L5
ldr x0, [sp,8]
b .L6
.L5:
ldr x0, [sp]
.L6:
add sp, sp, 16
ret

, :

12.31: GCC 4.9.1 x64


my_max:
; RDI=A
; RSI=B
; A B:
cmp rdi, rsi
; B RAX :
mov rax, rsi
; A>=B, A (RDI) RAX .
; , ( A<B)
cmovge rax, rdi
ret

my_min:
; RDI=A
; RSI=B
; A B:
cmp rdi, rsi
; B RAX :
mov rax, rsi
; A<=B, A (RDI) RAX .
; , ( A>B)
cmovle rax, rdi
ret

MSVC 2013 .
ARM64 CSEL, , MOVcc ARM CMOVcc x86, :
Conditional SELect.

143
12. 12.
12.32: GCC 4.9.1 ARM64
my_max:
; X0=A
; X1=B
; A B:
cmp x0, x1
; X0 (A) X0 X0>=X1 A>=B (Greater or Equal: )
; X1 (B) X0 A<B
csel x0, x0, x1, ge
ret

my_min:
; X0=A
; X1=B
; A B:
cmp x0, x1
; X0 (A) X0 X0<=X1 (Less or Equal: )
; X1 (B) X0 A>B
csel x0, x0, x1, le
ret

12.4.3. MIPS

GCC 4.4.5 MIPS , :

12.33: GCC 4.4.5 (IDA)


my_max:
; $v1 to 1, if 1, $a1<$a0:
slt $v1, $a1, $a0
; , $a1<$a0:
beqz $v1, locret_10
; branch delay slot
; $a1 $v0 , :
move $v0, $a1
; , $a0 $v0:
move $v0, $a0

locret_10:
jr $ra
or $at, $zero ; branch delay slot, NOP

; min() , SLT :
my_min:
slt $v1, $a0, $a1
beqz $v1, locret_28
move $v0, $a1
move $v0, $a0

locret_28:
jr $ra
or $at, $zero ; branch delay slot, NOP

branch delay slots: MOVE BEQZ, MOVE


.

12.5.

12.5.1. x86

12.34: x86
CMP register, register/value
Jcc true ; cc=

144
12. 12.
false:
... , , ...
JMP exit
true:
... , , ...
exit:

12.5.2. ARM

12.35: ARM
CMP register, register/value
Bcc true ; cc=
false:
... , , ...
JMP exit
true:
... , , ...
exit:

12.5.3. MIPS

12.36:
BEQZ REG, label
...

12.37: ?
BLTZ REG, label
...

12.38:
BEQ REG1, REG2, label
...

12.39:
BNE REG1, REG2, label
...

12.40: , ()
SLT REG1, REG2, REG3
BEQ REG1, label
...

12.41: , ()
SLTU REG1, REG2, REG3
BEQ REG1, label
...

12.5.4.

, : MOVcc
ARM ( ARM), CSEL ARM64, CMOVcc x86.

145
12. 12.
ARM

ARM :

12.42: ARM ( ARM)


CMP register, register/value
instr1_cc ; , ,
instr2_cc ; , ,
... .....

, CPU
.
Thumb IT, 4 , .
: 17.7.2 (. 260).

12.43: ARM ( Thumb)


CMP register, register/value
ITEEE EQ ; : ifthenelseelseelse
instr1 ; ,
instr2 ; ,
instr3 ; ,
instr4 ; ,

12.6.
(ARM64) .12.23 , -
CSEL.

146
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT

13

switch()/case/default

13.1.

#include <stdio.h>

void f (int a)
{
switch (a)
{
case 0: printf ("zero\n"); break;
case 1: printf ("one\n"); break;
case 2: printf ("two\n"); break;
default: printf ("something unknown\n"); break;
};
};

int main()
{
f (2); // test
};

13.1.1. x86

MSVC

(MSVC 2010):

13.1: MSVC 2010


tv64 = 4 ; size = 4
_a$ = 8 ; size = 4
_f PROC
push ebp
mov ebp, esp
push ecx
mov eax, DWORD PTR _a$[ebp]
mov DWORD PTR tv64[ebp], eax
cmp DWORD PTR tv64[ebp], 0
je SHORT $LN4@f
cmp DWORD PTR tv64[ebp], 1
je SHORT $LN3@f
cmp DWORD PTR tv64[ebp], 2
je SHORT $LN2@f
jmp SHORT $LN1@f
$LN4@f:
push OFFSET $SG739 ; 'zero', 0aH, 00H
call _printf
add esp, 4
jmp SHORT $LN7@f
$LN3@f:
push OFFSET $SG741 ; 'one', 0aH, 00H

147
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
call _printf
add esp, 4
jmp SHORT $LN7@f
$LN2@f:
push OFFSET $SG743 ; 'two', 0aH, 00H
call _printf
add esp, 4
jmp SHORT $LN7@f
$LN1@f:
push OFFSET $SG745 ; 'something unknown', 0aH, 00H
call _printf
add esp, 4
$LN7@f:
mov esp, ebp
pop ebp
ret 0
_f ENDP

switch(), , -
:
void f (int a)
{
if (a==0)
printf ("zero\n");
else if (a==1)
printf ("one\n");
else if (a==2)
printf ("two\n");
else
printf ("something unknown\n");
};

, , -
switch(), if(). , switch()
if().
, , -
(a) v641 .
GCC 4.4.1, , (
-O3).

MSVC

MSVC (/Ox): cl 1.c /Fa1.asm /Ox

13.2: MSVC
_a$ = 8 ; size = 4
_f PROC
mov eax, DWORD PTR _a$[esp4]
sub eax, 0
je SHORT $LN4@f
sub eax, 1
je SHORT $LN3@f
sub eax, 1
je SHORT $LN2@f
mov DWORD PTR _a$[esp4], OFFSET $SG791 ; 'something unknown', 0aH, 00H
jmp _printf
$LN2@f:
mov DWORD PTR _a$[esp4], OFFSET $SG789 ; 'two', 0aH, 00H
jmp _printf
$LN3@f:
mov DWORD PTR _a$[esp4], OFFSET $SG787 ; 'one', 0aH, 00H
jmp _printf
$LN4@f:
mov DWORD PTR _a$[esp4], OFFSET $SG785 ; 'zero', 0aH, 00H
1 tv MSVC

148
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
jmp _printf
_f ENDP

-, .
: EAX 0. , , , 0 EAX
? , ZF ( , 0 0)
JE (Jump if Equal JZ Jump if Zero) $LN4@f,
'zero'. , , -
0, .
, , printf()
'something unknown'.
: , , : a,
printf() CALL, JMP. .
CALL . CALL (RA)
. ( ,
, - ESP) :
ESP RA
ESP+4 a
, printf(), ,
. , , .
, printf(),
f(), printf(). printf() stdout, RET,
RA , f(),
f().
, printf() f() . - longjmp()2 .
, , .
ARM printf() (6.2.1 (. 48)).

2 wikipedia

149
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
OllyDbg

, OllyDbg.

OllyDbg switch()-, . EAX -


2, :

. 13.1: OllyDbg: EAX ( )

150
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
0 2 EAX. , EAX 2. ZF 0, , -
:

. 13.2: OllyDbg: SUB

151
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
DEC EAX 1. 1 , ZF 0:

. 13.3: OllyDbg: DEC

152
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
DEC . EAX 0 ZF , :

. 13.4: OllyDbg: DEC

OllyDbg , .

153
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
two :

. 13.5: OllyDbg:

: 2 2 0x001EF850.

154
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
MOV 0x001EF850 (. ). . -
printf() MSVCR100.DLL ( /MD):

. 13.6: OllyDbg: printf() MSVCR100.DLL

printf() 0x00FF3010 .

155
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
printf():

. 13.7: OllyDbg: printf() MSVCR100.DLL

two .

156
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
F7 F8 ( , ) , f() main():

. 13.8: OllyDbg: main()

, printf() main(). RA -
f() main(). CALL 0x00FF1000 f().

13.1.2. ARM: Keil 6/2013 ( ARM)

.text:0000014C f1:
.text:0000014C 00 00 50 E3 CMP R0, #0
.text:00000150 13 0E 8F 02 ADREQ R0, aZero ; "zero\n"
.text:00000154 05 00 00 0A BEQ loc_170
.text:00000158 01 00 50 E3 CMP R0, #1
.text:0000015C 4B 0F 8F 02 ADREQ R0, aOne ; "one\n"
.text:00000160 02 00 00 0A BEQ loc_170
.text:00000164 02 00 50 E3 CMP R0, #2
.text:00000168 4A 0F 8F 12 ADRNE R0, aSomethingUnkno ; "something unknown\n"
.text:0000016C 4E 0F 8F 02 ADREQ R0, aTwo ; "two\n"
.text:00000170
.text:00000170 loc_170: ; CODE XREF: f1+8
.text:00000170 ; f1+14
.text:00000170 78 18 00 EA B __2printf

, , switch()
if().
, , , ADREQ ((Equal)),
R0 = 0, R0 zero\n. BEQ
loc_170, R0 = 0.
, , BEQ , ADREQ
R0 - ? , BEQ , CMP, ADREQ
.
. printf() , , (6.2.1
(. 48)). printf() .
CMP R0, #2 , a = 2 . , ADRNE (Not
Equal) R0 something unknown \n, a 0 1 ,
a . R0 = 2, R0 two\n
ADREQ.

157
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
13.1.3. ARM: Keil 6/2013 ( Thumb)

.text:000000D4 f1:
.text:000000D4 10 B5 PUSH {R4,LR}
.text:000000D6 00 28 CMP R0, #0
.text:000000D8 05 D0 BEQ zero_case
.text:000000DA 01 28 CMP R0, #1
.text:000000DC 05 D0 BEQ one_case
.text:000000DE 02 28 CMP R0, #2
.text:000000E0 05 D0 BEQ two_case
.text:000000E2 91 A0 ADR R0, aSomethingUnkno ; "something unknown\n"
.text:000000E4 04 E0 B default_case

.text:000000E6 zero_case: ; CODE XREF: f1+4


.text:000000E6 95 A0 ADR R0, aZero ; "zero\n"
.text:000000E8 02 E0 B default_case

.text:000000EA one_case: ; CODE XREF: f1+8


.text:000000EA 96 A0 ADR R0, aOne ; "one\n"
.text:000000EC 00 E0 B default_case

.text:000000EE two_case: ; CODE XREF: f1+C


.text:000000EE 97 A0 ADR R0, aTwo ; "two\n"
.text:000000F0 default_case ; CODE XREF: f1+10
.text:000000F0 ; f1+14
.text:000000F0 06 F0 7E F8 BL __2printf
.text:000000F4 10 BD POP {R4,PC}

, Thumb- ,
Thumb- x86 CISC, .

13.1.4. ARM64: GCC (Linaro) 4.9

.LC12:
.string "zero"
.LC13:
.string "one"
.LC14:
.string "two"
.LC15:
.string "something unknown"
f12:
stp x29, x30, [sp, 32]!
add x29, sp, 0
str w0, [x29,28]
ldr w0, [x29,28]
cmp w0, 1
beq .L34
cmp w0, 2
beq .L35
cmp w0, wzr
bne .L38 ;
adrp x0, .LC12 ; "zero"
add x0, x0, :lo12:.LC12
bl puts
b .L32
.L34:
adrp x0, .LC13 ; "one"
add x0, x0, :lo12:.LC13
bl puts
b .L32
.L35:
adrp x0, .LC14 ; "two"
add x0, x0, :lo12:.LC14
bl puts
b .L32
.L38:
adrp x0, .LC15 ; "something unknown"

158
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
add x0, x0, :lo12:.LC15
bl puts
nop
.L32:
ldp x29, x30, [sp], 32
ret

int, W0, X0.


puts() ADRP/ADD, Hello, world!: 3.4.5
(. 17).

13.1.5. ARM64: GCC (Linaro) 4.9

f12:
cmp w0, 1
beq .L31
cmp w0, 2
beq .L32
cbz w0, .L35
;
adrp x0, .LC15 ; "something unknown"
add x0, x0, :lo12:.LC15
b puts
.L35:
adrp x0, .LC12 ; "zero"
add x0, x0, :lo12:.LC12
b puts
.L32:
adrp x0, .LC14 ; "two"
add x0, x0, :lo12:.LC14
b puts
.L31:
adrp x0, .LC13 ; "one"
add x0, x0, :lo12:.LC13
b puts

. CBZ (Compare and Branch on Zero )


W0 . puts() , : 13.1.1
(. 148).

13.1.6. MIPS

13.3: GCC 4.4.5 (IDA)


f:
lui $gp, (__gnu_local_gp >> 16)
; 1?
li $v0, 1
beq $a0, $v0, loc_60
la $gp, (__gnu_local_gp & 0xFFFF) ; branch delay slot
; 2?
li $v0, 2
beq $a0, $v0, loc_4C
or $at, $zero ; branch delay slot, NOP
; , 0:
bnez $a0, loc_38
or $at, $zero ; branch delay slot, NOP
; :
lui $a0, ($LC0 >> 16) # "zero"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; load delay slot, NOP
jr $t9 ; branch delay slot, NOP
la $a0, ($LC0 & 0xFFFF) # "zero" ; branch delay slot
#

loc_38: # CODE XREF: f+1C

159
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
lui $a0, ($LC3 >> 16) # "something unknown"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; load delay slot, NOP
jr $t9
la $a0,
($LC3 & 0xFFFF) # "something unknown" ; branch delay slot
#

loc_4C: # CODE XREF: f+14


lui $a0, ($LC2 >> 16) # "two"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; load delay slot, NOP
jr $t9
la $a0,
($LC2 & 0xFFFF) # "two" ; branch delay slot
#

loc_60: # CODE XREF: f+8


lui $a0, ($LC1 >> 16) # "one"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; load delay slot, NOP
jr $t9
la $a0, ($LC1 & 0xFFFF) # "one" ; branch delay slot

puts(), puts() (JR: Jump Register)


RA (jump and link). : 13.1.1 (. 148).
NOP- LW. load delay slot: delay slot MIPS. LW
, LW . ,
LW. MIPS- , LW,
, GCC NOP- . ,
.

13.1.7.

switch() if/else: .13.1.1.

13.2.
, JE/ JNE .
#include <stdio.h>

void f (int a)
{
switch (a)
{
case 0: printf ("zero\n"); break;
case 1: printf ("one\n"); break;
case 2: printf ("two\n"); break;
case 3: printf ("three\n"); break;
case 4: printf ("four\n"); break;
default: printf ("something unknown\n"); break;
};
};

int main()
{
f (2); // test
};

13.2.1. x86

MSVC

, (MSVC 2010):

160
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
13.4: MSVC 2010
tv64 = 4 ; size = 4
_a$ = 8 ; size = 4
_f PROC
push ebp
mov ebp, esp
push ecx
mov eax, DWORD PTR _a$[ebp]
mov DWORD PTR tv64[ebp], eax
cmp DWORD PTR tv64[ebp], 4
ja SHORT $LN1@f
mov ecx, DWORD PTR tv64[ebp]
jmp DWORD PTR $LN11@f[ecx*4]
$LN6@f:
push OFFSET $SG739 ; 'zero', 0aH, 00H
call _printf
add esp, 4
jmp SHORT $LN9@f
$LN5@f:
push OFFSET $SG741 ; 'one', 0aH, 00H
call _printf
add esp, 4
jmp SHORT $LN9@f
$LN4@f:
push OFFSET $SG743 ; 'two', 0aH, 00H
call _printf
add esp, 4
jmp SHORT $LN9@f
$LN3@f:
push OFFSET $SG745 ; 'three', 0aH, 00H
call _printf
add esp, 4
jmp SHORT $LN9@f
$LN2@f:
push OFFSET $SG747 ; 'four', 0aH, 00H
call _printf
add esp, 4
jmp SHORT $LN9@f
$LN1@f:
push OFFSET $SG749 ; 'something unknown', 0aH, 00H
call _printf
add esp, 4
$LN9@f:
mov esp, ebp
pop ebp
ret 0
npad 2 ;
$LN11@f:
DD $LN6@f ; 0
DD $LN5@f ; 1
DD $LN4@f ; 2
DD $LN3@f ; 3
DD $LN2@f ; 4
_f ENDP

: printf() . ,
, , , .
$LN11@f.
, a 4, $LN1@f, printf() -
'something unknown'.
a 4, 4 ($LN11@f).
, , . ,
a 2. 2 4 = 8 ( 32- , ,
4 ). 8 $LN11@f , $LN4@f. JMP
$LN4@f .
jumptable branch table3 .
3 computed GOTO FORTRAN: wikipedia. - , !

161
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
printf() 'two'. , jmp DWORD PTR $LN11@f[ecx*4]
DWORD, $LN11@f + ecx * 4.
npad (88 (. 895)) , , -
4 ( 16). , 32-
, -, ..

162
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
OllyDbg

OllyDbg. (2) EAX:

. 13.9: OllyDbg: EAX

163
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
, 4? , (default) :

. 13.10: OllyDbg: 2 4:

164
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
jumptable:

. 13.11: OllyDbg: jumptable

, Follow in Dump Address constant, jumptable . 5 32-


4 . ECX 2, ( ) . ,
Follow in Dump Memory address OllyDbg ,
JMP. 0x010B103A.

4 OllyDbg, FIXUP-: 68.2.6 (. 714),

165
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
0x010B103A: , two:

. 13.12: OllyDbg: case:

GCC

, GCC 4.4.1:

13.5: GCC 4.4.1


public f
f proc near ; CODE XREF: main+10

var_18 = dword ptr 18h


arg_0 = dword ptr 8

push ebp
mov ebp, esp
sub esp, 18h
cmp [ebp+arg_0], 4
ja short loc_8048444
mov eax, [ebp+arg_0]
shl eax, 2
mov eax, ds:off_804855C[eax]
jmp eax

loc_80483FE: ; DATA XREF: .rodata:off_804855C


mov [esp+18h+var_18], offset aZero ; "zero"
call _puts
jmp short locret_8048450

loc_804840C: ; DATA XREF: .rodata:08048560


mov [esp+18h+var_18], offset aOne ; "one"
call _puts
jmp short locret_8048450

loc_804841A: ; DATA XREF: .rodata:08048564


mov [esp+18h+var_18], offset aTwo ; "two"
call _puts
jmp short locret_8048450

loc_8048428: ; DATA XREF: .rodata:08048568

166
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
mov [esp+18h+var_18], offset aThree ; "three"
call _puts
jmp short locret_8048450

loc_8048436: ; DATA XREF: .rodata:0804856C


mov [esp+18h+var_18], offset aFour ; "four"
call _puts
jmp short locret_8048450

loc_8048444: ; CODE XREF: f+A


mov [esp+18h+var_18], offset aSomethingUnkno ; "something unknown"
call _puts

locret_8048450: ; CODE XREF: f+26


; f+34...
leave
retn
f endp

off_804855C dd offset loc_80483FE ; DATA XREF: f+12


dd offset loc_804840C
dd offset loc_804841A
dd offset loc_8048428
dd offset loc_8048436

, : arg_0 4
2 ( 4) (16.2.1 (. 215)).
off_804855C .

13.2.2. ARM: Keil 6/2013 ( ARM)

13.6: Keil 6/2013 ( ARM)


00000174 f2
00000174 05 00 50 E3 CMP R0, #5 ; switch 5 cases
00000178 00 F1 8F 30 ADDCC PC, PC, R0,LSL#2 ; switch jump
0000017C 0E 00 00 EA B default_case ; jumptable 00000178 default case

00000180
00000180 loc_180 ; CODE XREF: f2+4
00000180 03 00 00 EA B zero_case ; jumptable 00000178 case 0

00000184
00000184 loc_184 ; CODE XREF: f2+4
00000184 04 00 00 EA B one_case ; jumptable 00000178 case 1

00000188
00000188 loc_188 ; CODE XREF: f2+4
00000188 05 00 00 EA B two_case ; jumptable 00000178 case 2

0000018C
0000018C loc_18C ; CODE XREF: f2+4
0000018C 06 00 00 EA B three_case ; jumptable 00000178 case 3

00000190
00000190 loc_190 ; CODE XREF: f2+4
00000190 07 00 00 EA B four_case ; jumptable 00000178 case 4

00000194
00000194 zero_case ; CODE XREF: f2+4
00000194 ; f2:loc_180
00000194 EC 00 8F E2 ADR R0, aZero ; jumptable 00000178 case 0
00000198 06 00 00 EA B loc_1B8

0000019C
0000019C one_case ; CODE XREF: f2+4
0000019C ; f2:loc_184
0000019C EC 00 8F E2 ADR R0, aOne ; jumptable 00000178 case 1

167
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
000001A0 04 00 00 EA B loc_1B8

000001A4
000001A4 two_case ; CODE XREF: f2+4
000001A4 ; f2:loc_188
000001A4 01 0C 8F E2 ADR R0, aTwo ; jumptable 00000178 case 2
000001A8 02 00 00 EA B loc_1B8

000001AC
000001AC three_case ; CODE XREF: f2+4
000001AC ; f2:loc_18C
000001AC 01 0C 8F E2 ADR R0, aThree ; jumptable 00000178 case 3
000001B0 00 00 00 EA B loc_1B8

000001B4
000001B4 four_case ; CODE XREF: f2+4
000001B4 ; f2:loc_190
000001B4 01 0C 8F E2 ADR R0, aFour ; jumptable 00000178 case 4
000001B8
000001B8 loc_1B8 ; CODE XREF: f2+24
000001B8 ; f2+2C
000001B8 66 18 00 EA B __2printf

000001BC
000001BC default_case ; CODE XREF: f2+4
000001BC ; f2+8
000001BC D4 00 8F E2 ADR R0, aSomethingUnkno ; jumptable 00000178 default case
000001C0 FC FF FF EA B loc_1B8

ARM,
4 .
, , a 4: , something
unknown\n.
CMP R0, #5 a c 5.
ADDCC PC, PC, R0,LSL#2 5 R0 < 5 (CC=Carry clear / Less than).
, ADDCC ( R0 5), default_case.
R0 < 5 ADDCC , .
R0 4. , LSL#2 2 .
(16.2.1 (. 215)) , 2 e 4.
R0 4 PC, , , -
B (Branch).
ADDCC, PC 8 (0x180),
ADDCC (0x178), , , 2 .
ARM: ADDCC, -
, PC . .
a = 0, PC PC PC (
8) loc_180. 8 , ADDCC.
a = 1, PC P C + 8 + a 4 = P C + 8 + 1 4 = P C + 12 = 0x184. loc_184.
a PC 4. 4 ARM -
, B, 5 .
B , ,
switch(). , ..

13.2.3. ARM: Keil 6/2013 ( Thumb)

13.7: Keil 6/2013 ( Thumb)


000000F6 EXPORT f2
000000F6 f2
5 ADD

168
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
000000F6 10 B5 PUSH {R4,LR}
000000F8 03 00 MOVS R3, R0
000000FA 06 F0 69 F8 BL __ARM_common_switch8_thumb ; switch 6 cases

000000FE 05 DCB 5
000000FF 04 06 08 0A 0C 10 DCB 4, 6, 8, 0xA, 0xC, 0x10 ; jump table for switch statement
00000105 00 ALIGN 2
00000106
00000106 zero_case ; CODE XREF: f2+4
00000106 8D A0 ADR R0, aZero ; jumptable 000000FA case 0
00000108 06 E0 B loc_118

0000010A
0000010A one_case ; CODE XREF: f2+4
0000010A 8E A0 ADR R0, aOne ; jumptable 000000FA case 1
0000010C 04 E0 B loc_118

0000010E
0000010E two_case ; CODE XREF: f2+4
0000010E 8F A0 ADR R0, aTwo ; jumptable 000000FA case 2
00000110 02 E0 B loc_118

00000112
00000112 three_case ; CODE XREF: f2+4
00000112 90 A0 ADR R0, aThree ; jumptable 000000FA case 3
00000114 00 E0 B loc_118

00000116
00000116 four_case ; CODE XREF: f2+4
00000116 91 A0 ADR R0, aFour ; jumptable 000000FA case 4
00000118
00000118 loc_118 ; CODE XREF: f2+12
00000118 ; f2+16
00000118 06 F0 6A F8 BL __2printf
0000011C 10 BD POP {R4,PC}

0000011E
0000011E default_case ; CODE XREF: f2+4
0000011E 82 A0 ADR R0, aSomethingUnkno ; jumptable 000000FA default case
00000120 FA E7 B loc_118

000061D0 EXPORT __ARM_common_switch8_thumb


000061D0 __ARM_common_switch8_thumb ; CODE XREF: example6_f2+4
000061D0 78 47 BX PC

000061D2 00 00 ALIGN 4
000061D2 ; End of function __ARM_common_switch8_thumb
000061D2
000061D4 __32__ARM_common_switch8_thumb ; CODE XREF: __ARM_common_switch8_thumb
000061D4 01 C0 5E E5 LDRB R12, [LR,#1]
000061D8 0C 00 53 E1 CMP R3, R12
000061DC 0C 30 DE 27 LDRCSB R3, [LR,R12]
000061E0 03 30 DE 37 LDRCCB R3, [LR,R3]
000061E4 83 C0 8E E0 ADD R12, LR, R3,LSL#1
000061E8 1C FF 2F E1 BX R12
000061E8 ; End of function __32__ARM_common_switch8_thumb

Thumb Thumb-2 , . ,
, x86.
, , ,
, , . ,
.
, __ARM_common_switch8_thumb.
BX PC , ARM-. ,
. , .

169
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
, LR . ,
, LR BL __ARM_common_switch8_thumb ,
.
, , -
switch().
IDA
jumptable 000000FA case 0.

13.2.4. MIPS

13.8: GCC 4.4.5 (IDA)


f:
lui $gp, (__gnu_local_gp >> 16)
; loc_24, 5:
sltiu $v0, $a0, 5
bnez $v0, loc_24
la $gp, (__gnu_local_gp & 0xFFFF) ; branch delay slot
; 5
; "something unknown" :
lui $a0, ($LC5 >> 16) # "something unknown"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; NOP
jr $t9
la $a0, ($LC5 & 0xFFFF) # "something unknown" ; branch delay slot

loc_24: # CODE XREF: f+8


;
; LA , LUI ADDIU:
la $v0, off_120
; 4:
sll $a0, 2
; :
addu $a0, $v0, $a0
; :
lw $v0, 0($a0)
or $at, $zero ; NOP
; , :
jr $v0
or $at, $zero ; branch delay slot, NOP

sub_44: # DATA XREF: .rodata:0000012C


; "three"
lui $a0, ($LC3 >> 16) # "three"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; NOP
jr $t9
la $a0, ($LC3 & 0xFFFF) # "three" ; branch delay slot

sub_58: # DATA XREF: .rodata:00000130


; "four"
lui $a0, ($LC4 >> 16) # "four"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; NOP
jr $t9
la $a0, ($LC4 & 0xFFFF) # "four" ; branch delay slot

sub_6C: # DATA XREF: .rodata:off_120


; "zero"
lui $a0, ($LC0 >> 16) # "zero"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; NOP
jr $t9
la $a0, ($LC0 & 0xFFFF) # "zero" ; branch delay slot

sub_80: # DATA XREF: .rodata:00000124


; "one"

170
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
lui $a0, ($LC1 >> 16) # "one"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; NOP
jr $t9
la $a0, ($LC1 & 0xFFFF) # "one" ; branch delay slot

sub_94: # DATA XREF: .rodata:00000128


; "two"
lui $a0, ($LC2 >> 16) # "two"
lw $t9, (puts & 0xFFFF)($gp)
or $at, $zero ; NOP
jr $t9
la $a0, ($LC2 & 0xFFFF) # "two" ; branch delay slot

; .rodata:
off_120: .word sub_6C
.word sub_80
.word sub_94
.word sub_44
.word sub_58

SLTIU (Set on Less Than Immediate Unsigned ,


, ). , SLTU (Set on Less Than Unsigned), I
immediate, .. .
BNEZ Branch if Not Equal to Zero ( ).
ISA. SLL (Shift Word Left Logical )
4. MIPS - 32- , (jumptable) 32-.

13.2.5.

switch():

13.9: x86
MOV REG, input
CMP REG, 4 ;
JA default
SHL REG, 2 ; . 3 x64
MOV REG, jump_table[REG]
JMP REG

case1:
; -
JMP exit
case2:
; -
JMP exit
case3:
; -
JMP exit
case4:
; -
JMP exit
case5:
; -
JMP exit

default:

...

exit:

....

jump_table dd case1
dd case2
dd case3

171
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
dd case4
dd case5

: JMP jump_table[REG*4].
JMP jump_table[REG*8] x64.
(jumptable) , : 18.5 (. 285).

13.3. case
: case :
#include <stdio.h>

void f(int a)
{
switch (a)
{
case 1:
case 2:
case 7:
case 10:
printf ("1, 2, 7, 10\n");
break;
case 3:
case 4:
case 5:
case 6:
printf ("3, 4, 5\n");
break;
case 8:
case 9:
case 20:
case 21:
printf ("8, 9, 21\n");
break;
case 22:
printf ("22\n");
break;
default:
printf ("default\n");
break;
};
};

int main()
{
f(4);
};

,
.

13.3.1. MSVC

13.10: MSVC 2010


1 $SG2798 DB '1, 2, 7, 10', 0aH, 00H
2 $SG2800 DB '3, 4, 5', 0aH, 00H
3 $SG2802 DB '8, 9, 21', 0aH, 00H
4 $SG2804 DB '22', 0aH, 00H
5 $SG2806 DB 'default', 0aH, 00H
6
7 _a$ = 8
8 _f PROC
9 mov eax, DWORD PTR _a$[esp4]
10 dec eax

172
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
11 cmp eax, 21
12 ja SHORT $LN1@f
13 movzx eax, BYTE PTR $LN10@f[eax]
14 jmp DWORD PTR $LN11@f[eax*4]
15 $LN5@f:
16 mov DWORD PTR _a$[esp4], OFFSET $SG2798 ; '1, 2, 7, 10'
17 jmp DWORD PTR __imp__printf
18 $LN4@f:
19 mov DWORD PTR _a$[esp4], OFFSET $SG2800 ; '3, 4, 5'
20 jmp DWORD PTR __imp__printf
21 $LN3@f:
22 mov DWORD PTR _a$[esp4], OFFSET $SG2802 ; '8, 9, 21'
23 jmp DWORD PTR __imp__printf
24 $LN2@f:
25 mov DWORD PTR _a$[esp4], OFFSET $SG2804 ; '22'
26 jmp DWORD PTR __imp__printf
27 $LN1@f:
28 mov DWORD PTR _a$[esp4], OFFSET $SG2806 ; 'default'
29 jmp DWORD PTR __imp__printf
30 npad 2 ; $LN11@f 16-
31 $LN11@f:
32 DD $LN5@f ; '1, 2, 7, 10'
33 DD $LN4@f ; '3, 4, 5'
34 DD $LN3@f ; '8, 9, 21'
35 DD $LN2@f ; '22'
36 DD $LN1@f ; 'default'
37 $LN10@f:
38 DB 0 ; a=1
39 DB 0 ; a=2
40 DB 1 ; a=3
41 DB 1 ; a=4
42 DB 1 ; a=5
43 DB 1 ; a=6
44 DB 0 ; a=7
45 DB 2 ; a=8
46 DB 2 ; a=9
47 DB 0 ; a=10
48 DB 4 ; a=11
49 DB 4 ; a=12
50 DB 4 ; a=13
51 DB 4 ; a=14
52 DB 4 ; a=15
53 DB 4 ; a=16
54 DB 4 ; a=17
55 DB 4 ; a=18
56 DB 4 ; a=19
57 DB 2 ; a=20
58 DB 2 ; a=21
59 DB 3 ; a=22
60 _f ENDP

: ($LN10@f) , ($LN11@f)
.
, ( 13).
: 0 case ( 1, 2, 7, 10), 1 (
3, 4, 5), 2 ( 8, 9, 21), 3 ( 22), 4 .
( 14).
, . DEC
10 a = 1. a = 0.
.
? , (13.2.1 (. 166)), ,
? , 8- ,
.

173
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
13.3.2. GCC

GCC , (13.2.1 (. 166)), .

13.3.3. ARM64: GCC 4.9.1

-, , 0, GCC
, 1.
GCC 4.9.1 ARM64 . 8- .
, ARM64 4 . GCC ,
. .

13.11: GCC 4.9.1 ARM64


f14:
; W0
sub w0, w0, #1
cmp w0, 21
; ():
bls .L9
.L2:
; "default":
adrp x0, .LC4
add x0, x0, :lo12:.LC4
b puts
.L9:
; X1:
adrp x1, .L4
add x1, x1, :lo12:.L4
; W0=input_value1
; :
ldrb w0, [x1,w0,uxtw]
; Lrtx:
adr x1, .Lrtx4
; 4 ( 2 ) ( ) Lrtx:
add x0, x1, w0, sxtb #2
; :
br x0
; (text):
.Lrtx4:
.section .rodata
; ".section" (rodata):
.L4:
.byte (.L3 .Lrtx4) / 4 ; case 1
.byte (.L3 .Lrtx4) / 4 ; case 2
.byte (.L5 .Lrtx4) / 4 ; case 3
.byte (.L5 .Lrtx4) / 4 ; case 4
.byte (.L5 .Lrtx4) / 4 ; case 5
.byte (.L5 .Lrtx4) / 4 ; case 6
.byte (.L3 .Lrtx4) / 4 ; case 7
.byte (.L6 .Lrtx4) / 4 ; case 8
.byte (.L6 .Lrtx4) / 4 ; case 9
.byte (.L3 .Lrtx4) / 4 ; case 10
.byte (.L2 .Lrtx4) / 4 ; case 11
.byte (.L2 .Lrtx4) / 4 ; case 12
.byte (.L2 .Lrtx4) / 4 ; case 13
.byte (.L2 .Lrtx4) / 4 ; case 14
.byte (.L2 .Lrtx4) / 4 ; case 15
.byte (.L2 .Lrtx4) / 4 ; case 16
.byte (.L2 .Lrtx4) / 4 ; case 17
.byte (.L2 .Lrtx4) / 4 ; case 18
.byte (.L2 .Lrtx4) / 4 ; case 19
.byte (.L6 .Lrtx4) / 4 ; case 20
.byte (.L6 .Lrtx4) / 4 ; case 21
.byte (.L7 .Lrtx4) / 4 ; case 22
.text
; ".text" (text):
.L7:

174
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
; "22"
adrp x0, .LC3
add x0, x0, :lo12:.LC3
b puts
.L6:
; "8, 9, 21"
adrp x0, .LC2
add x0, x0, :lo12:.LC2
b puts
.L5:
; "3, 4, 5"
adrp x0, .LC1
add x0, x0, :lo12:.LC1
b puts
.L3:
; "1, 2, 7, 10"
adrp x0, .LC0
add x0, x0, :lo12:.LC0
b puts
.LC0:
.string "1, 2, 7, 10"
.LC1:
.string "3, 4, 5"
.LC2:
.string "8, 9, 21"
.LC3:
.string "22"
.LC4:
.string "default"

IDA. :

13.12: jumptable in IDA


.rodata:0000000000000064 AREA .rodata, DATA, READONLY
.rodata:0000000000000064 ; ORG 0x64
.rodata:0000000000000064 $d DCB 9 ; case 1
.rodata:0000000000000065 DCB 9 ; case 2
.rodata:0000000000000066 DCB 6 ; case 3
.rodata:0000000000000067 DCB 6 ; case 4
.rodata:0000000000000068 DCB 6 ; case 5
.rodata:0000000000000069 DCB 6 ; case 6
.rodata:000000000000006A DCB 9 ; case 7
.rodata:000000000000006B DCB 3 ; case 8
.rodata:000000000000006C DCB 3 ; case 9
.rodata:000000000000006D DCB 9 ; case 10
.rodata:000000000000006E DCB 0xF7 ; case 11
.rodata:000000000000006F DCB 0xF7 ; case 12
.rodata:0000000000000070 DCB 0xF7 ; case 13
.rodata:0000000000000071 DCB 0xF7 ; case 14
.rodata:0000000000000072 DCB 0xF7 ; case 15
.rodata:0000000000000073 DCB 0xF7 ; case 16
.rodata:0000000000000074 DCB 0xF7 ; case 17
.rodata:0000000000000075 DCB 0xF7 ; case 18
.rodata:0000000000000076 DCB 0xF7 ; case 19
.rodata:0000000000000077 DCB 3 ; case 20
.rodata:0000000000000078 DCB 3 ; case 21
.rodata:0000000000000079 DCB 0 ; case 22
.rodata:000000000000007B ; .rodata ends

1, 9 9 Lrtx4. 22, 0 4,
0. Lrtx4 L7, , 22.
, .rodata ( ).
(0xF7). , , default
( .L2).

175
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
13.4. Fall-through
switch() .. fallthrough (). :
1 #define R 1
2 #define W 2
3 #define RW 3
4
5 void f(int type)
6 {
7 int read=0, write=0;
8
9 switch (type)
10 {
11 case RW:
12 read=1;
13 case W:
14 write=1;
15 break;
16 case R:
17 read=1;
18 break;
19 default:
20 break;
21 };
22 printf ("read=%d, write=%d\n", read, write);
23 };

type = 1 (R), read 1, type = 2 (W), write 2. type = 3 (RW),


read write 1.
14 : type = RW type = W . break
case RW, .

13.4.1. MSVC x86

13.13: MSVC 2012


$SG1305 DB 'read=%d, write=%d', 0aH, 00H

_write$ = 12 ; size = 4
_read$ = 8 ; size = 4
tv64 = 4 ; size = 4
_type$ = 8 ; size = 4
_f PROC
push ebp
mov ebp, esp
sub esp, 12
mov DWORD PTR _read$[ebp], 0
mov DWORD PTR _write$[ebp], 0
mov eax, DWORD PTR _type$[ebp]
mov DWORD PTR tv64[ebp], eax
cmp DWORD PTR tv64[ebp], 1 ; R
je SHORT $LN2@f
cmp DWORD PTR tv64[ebp], 2 ; W
je SHORT $LN3@f
cmp DWORD PTR tv64[ebp], 3 ; RW
je SHORT $LN4@f
jmp SHORT $LN5@f
$LN4@f: ; case RW:
mov DWORD PTR _read$[ebp], 1
$LN3@f: ; case W:
mov DWORD PTR _write$[ebp], 1
jmp SHORT $LN5@f
$LN2@f: ; case R:
mov DWORD PTR _read$[ebp], 1
$LN5@f: ; default
mov ecx, DWORD PTR _write$[ebp]
push ecx

176
13. SWITCH()/CASE/DEFAULT 13. SWITCH()/CASE/DEFAULT
mov edx, DWORD PTR _read$[ebp]
push edx
push OFFSET $SG1305 ; 'read=%d, write=%d'
call _printf
add esp, 12
mov esp, ebp
pop ebp
ret 0
_f ENDP

, . $LN4@f $LN3@f:
(code ow) $LN4@f, read 1, write. ,
: ( read)
( write). type = W , $LN3@f, read 1 .

13.4.2. ARM64

13.14: GCC (Linaro) 4.9


.LC0:
.string "read=%d, write=%d\n"
f:
stp x29, x30, [sp, 48]!
add x29, sp, 0
str w0, [x29,28]
str wzr, [x29,44] ; "read" "write"
str wzr, [x29,40]
ldr w0, [x29,28] ; "type"
cmp w0, 2 ; type=W?
beq .L3
cmp w0, 3 ; type=RW?
beq .L4
cmp w0, 1 ; type=R?
beq .L5
b .L6 ; ...
.L4: ; case RW
mov w0, 1
str w0, [x29,44] ; read=1
.L3: ; case W
mov w0, 1
str w0, [x29,40] ; write=1
b .L6
.L5: ; case R
mov w0, 1
str w0, [x29,44] ; read=1
nop
.L6: ; default
adrp x0, .LC0 ; "read=%d, write=%d\n"
add x0, x0, :lo12:.LC0
ldr w1, [x29,44] ; "read"
ldr w2, [x29,40] ; "write"
bl printf
ldp x29, x30, [sp], 48
ret

. .L4 .L3.

13.5.

13.5.1. #1

13.2 (. 160) ,
, . .
: G.1.5 (. 986).

177
14. 14.

14

14.1.

14.1.1. x86

x86 LOOP. ECX


0, ECX , . , -
, , .
- LOOP, .

, /++ for(), while(), do/while().


for().
, , (/)
.
for (; ; )
{
_;
}

, .
:
#include <stdio.h>

void printing_function(int i)
{
printf ("f(%d)\n", i);
};

int main()
{
int i;

for (i=2; i<10; i++)


printing_function(i);

return 0;
};

(MSVC 2010):

14.1: MSVC 2010


_i$ = 4
_main PROC
push ebp
mov ebp, esp
push ecx
mov DWORD PTR _i$[ebp], 2 ;
jmp SHORT $LN3@main

178
14. 14.
$LN2@main:
mov eax, DWORD PTR _i$[ebp] ; :
add eax, 1 ; 1 i
mov DWORD PTR _i$[ebp], eax
$LN3@main:
cmp DWORD PTR _i$[ebp], 10 ; **
jge SHORT $LN1@main ; i 10,
mov ecx, DWORD PTR _i$[ebp] ; : printing_function(i)
push ecx
call _printing_function
add esp, 4
jmp SHORT $LN2@main ;
$LN1@main: ;
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP

, .
GCC 4.4.1 , :

14.2: GCC 4.4.1


main proc near

var_20 = dword ptr 20h


var_4 = dword ptr 4

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 20h
mov [esp+20h+var_4], 2 ; i
jmp short loc_8048476

loc_8048465:
mov eax, [esp+20h+var_4]
mov [esp+20h+var_20], eax
call printing_function
add [esp+20h+var_4], 1 ; i

loc_8048476:
cmp [esp+20h+var_4], 9
jle short loc_8048465 ; i<=9,
mov eax, 0
leave
retn
main endp

, MSVC 2010 (/Ox):

14.3: MSVC
_main PROC
push esi
mov esi, 2
$LL3@main:
push esi
call _printing_function
inc esi
add esp, 4
cmp esi, 10 ; 0000000aH
jl SHORT $LL3@main
xor eax, eax
pop esi
ret 0
_main ENDP

179
14. 14.
: i ,
: ESI. , .
, , : f() ESI. -
, ESI f(),
. : PUSH ESI/POP ESI
.
GCC 4.4.1 (-O3):

14.4: GCC 4.4.1


main proc near

var_10 = dword ptr 10h

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 10h
mov [esp+10h+var_10], 2
call printing_function
mov [esp+10h+var_10], 3
call printing_function
mov [esp+10h+var_10], 4
call printing_function
mov [esp+10h+var_10], 5
call printing_function
mov [esp+10h+var_10], 6
call printing_function
mov [esp+10h+var_10], 7
call printing_function
mov [esp+10h+var_10], 8
call printing_function
mov [esp+10h+var_10], 9
call printing_function
xor eax, eax
leave
retn
main endp

GCC 1 .
, ( ) ,
, . , .
, -
-2 .

i 100 . GCC :

14.5: GCC
public main
main proc near

var_20 = dword ptr 20h

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
push ebx
mov ebx, 2 ; i=2
sub esp, 1Ch

; loc_80484D0 ( ) 16- :
nop

loc_80484D0:
; i printing_function():
1 loop unwinding
2 : [Dre07]. Intel : [Int14, . 3.4.1.7].

180
14. 14.
mov [esp+20h+var_20], ebx
add ebx, 1 ; i++
call printing_function
cmp ebx, 64h ; i==100?
jnz short loc_80484D0 ; ,
add esp, 1Ch
xor eax, eax ; 0
pop ebx
mov esp, ebp
pop ebp
retn
main endp

, MSVC 2010 (/Ox). ,


i EBX. GCC , f(),
, , main().

181
14. 14.
14.1.2. x86: OllyDbg

MSVC 2010 /Ox /Ob0 OllyDbg.


, OllyDbg , :

. 14.1: OllyDbg: main()

(F8 , ) , ESI 1. , ESI = i = 6:

. 14.2: OllyDbg: i = 6

9 . JL :

. 14.3: OllyDbg: ESI = 10,

14.1.3. x86: tracer

, . tracer.
IDA, PUSH ESI (
f(),) 0x401026 tracer:
tracer.exe l:loops_2.exe bpx=loops_2.exe!0x00401026

BPX tracer .
tracer.log :

182
14. 14.

PID=12884|New process loops_2.exe


(0) loops_2.exe!0x401026
EAX=0x00a328c8 EBX=0x00000000 ECX=0x6f0f4714 EDX=0x00000000
ESI=0x00000002 EDI=0x00333378 EBP=0x0024fbfc ESP=0x0024fbb8
EIP=0x00331026
FLAGS=PF ZF IF
(0) loops_2.exe!0x401026
EAX=0x00000005 EBX=0x00000000 ECX=0x6f0a5617 EDX=0x000ee188
ESI=0x00000003 EDI=0x00333378 EBP=0x0024fbfc ESP=0x0024fbb8
EIP=0x00331026
FLAGS=CF PF AF SF IF
(0) loops_2.exe!0x401026
EAX=0x00000005 EBX=0x00000000 ECX=0x6f0a5617 EDX=0x000ee188
ESI=0x00000004 EDI=0x00333378 EBP=0x0024fbfc ESP=0x0024fbb8
EIP=0x00331026
FLAGS=CF PF AF SF IF
(0) loops_2.exe!0x401026
EAX=0x00000005 EBX=0x00000000 ECX=0x6f0a5617 EDX=0x000ee188
ESI=0x00000005 EDI=0x00333378 EBP=0x0024fbfc ESP=0x0024fbb8
EIP=0x00331026
FLAGS=CF AF SF IF
(0) loops_2.exe!0x401026
EAX=0x00000005 EBX=0x00000000 ECX=0x6f0a5617 EDX=0x000ee188
ESI=0x00000006 EDI=0x00333378 EBP=0x0024fbfc ESP=0x0024fbb8
EIP=0x00331026
FLAGS=CF PF AF SF IF
(0) loops_2.exe!0x401026
EAX=0x00000005 EBX=0x00000000 ECX=0x6f0a5617 EDX=0x000ee188
ESI=0x00000007 EDI=0x00333378 EBP=0x0024fbfc ESP=0x0024fbb8
EIP=0x00331026
FLAGS=CF AF SF IF
(0) loops_2.exe!0x401026
EAX=0x00000005 EBX=0x00000000 ECX=0x6f0a5617 EDX=0x000ee188
ESI=0x00000008 EDI=0x00333378 EBP=0x0024fbfc ESP=0x0024fbb8
EIP=0x00331026
FLAGS=CF AF SF IF
(0) loops_2.exe!0x401026
EAX=0x00000005 EBX=0x00000000 ECX=0x6f0a5617 EDX=0x000ee188
ESI=0x00000009 EDI=0x00333378 EBP=0x0024fbfc ESP=0x0024fbb8
EIP=0x00331026
FLAGS=CF PF AF SF IF
PID=12884|Process loops_2.exe exited. ExitCode=0 (0x0)

, ESI 2 9.
, tracer .
trace. , . .idc-
IDA, . , IDA main() 0x00401020 :
tracer.exe l:loops_2.exe bpf=loops_2.exe!0x00401020,trace:cc

BPF .
loops_2.exe.idc loops_2.exe_clear.idc.

183
14. 14.
loops_2.exe.idc IDA :

. 14.4: IDA .idc-

, ESI 2 9 , [3..0xA]. ,
main() 0 EAX.
tracer loops_2.exe.txt, , -
:

14.6: loops_2.exe.txt
0x401020 (.text+0x20), e= 1 [PUSH ESI] ESI=1
0x401021 (.text+0x21), e= 1 [MOV ESI, 2]
0x401026 (.text+0x26), e= 8 [PUSH ESI] ESI=2..9
0x401027 (.text+0x27), e= 8 [CALL 8D1000h] tracing nested maximum level (1) reached, skipping
this CALL 8D1000h=0x8d1000
0x40102c (.text+0x2c), e= 8 [INC ESI] ESI=2..9
0x40102d (.text+0x2d), e= 8 [ADD ESP, 4] ESP=0x38fcbc
0x401030 (.text+0x30), e= 8 [CMP ESI, 0Ah] ESI=3..0xa
0x401033 (.text+0x33), e= 8 [JL 8D1026h] SF=false,true OF=false
0x401035 (.text+0x35), e= 1 [XOR EAX, EAX]
0x401037 (.text+0x37), e= 1 [POP ESI]
0x401038 (.text+0x38), e= 1 [RETN] EAX=0

grep.

14.1.4. ARM

Keil 6/2013 ( ARM)

main
STMFD SP!, {R4,LR}
MOV R4, #2
B loc_368
loc_35C ; CODE XREF: main+1C
MOV R0, R4
BL printing_function
ADD R4, R4, #1

loc_368 ; CODE XREF: main+8


CMP R4, #0xA

184
14. 14.
BLT loc_35C
MOV R0, #0
LDMFD SP!, {R4,PC}

i R4.
MOV R4, #2 i.
MOV R0, R4 BL printing_function .,
, f() .
ADD R4, R4, #1 i .
CMP R4, #0xA i 0xA (10). BLT (Branch Less Than) ,
i 10.
R0 0 ( 0) .

Keil 6/2013 ( Thumb)

_main
PUSH {R4,LR}
MOVS R4, #2

loc_132 ; CODE XREF: _main+E


MOVS R0, R4
BL printing_function
ADDS R4, R4, #1
CMP R4, #0xA
BLT loc_132
MOVS R0, #0
POP {R4,PC}

Xcode 4.6.3 (LLVM) ( Thumb-2)

_main
PUSH {R4,R7,LR}
MOVW R4, #0x1124 ; "%d\n"
MOVS R1, #2
MOVT.W R4, #0
ADD R7, SP, #4
ADD R4, PC
MOV R0, R4
BLX _printf
MOV R0, R4
MOVS R1, #3
BLX _printf
MOV R0, R4
MOVS R1, #4
BLX _printf
MOV R0, R4
MOVS R1, #5
BLX _printf
MOV R0, R4
MOVS R1, #6
BLX _printf
MOV R0, R4
MOVS R1, #7
BLX _printf
MOV R0, R4
MOVS R1, #8
BLX _printf
MOV R0, R4
MOVS R1, #9
BLX _printf
MOVS R0, #0
POP {R4,R7,PC}

185
14. 14.
, f() :
void printing_function(int i)
{
printf ("%d\n", i);
};

LLVM , f() inline-,


8 . , ( )
, .

ARM64: GCC 4.9.1

14.7: GCC 4.9.1


printing_function:
; printf():
mov w1, w0
; "f(%d)\n"
adrp x0, .LC0
add x0, x0, :lo12:.LC0
; :
b printf
main:
; FP LR :
stp x29, x30, [sp, 32]!
; :
add x29, sp, 0
; X19 :
str x19, [sp,16]
; W19 .
; 2:
mov w19, 2
.L3:
; printing_function():
mov w0, w19
; .
add w19, w19, 1
; W0 .
bl printing_function
; ?
cmp w19, 10
; , :
bne .L3
; 0
mov w0, 0
; X19:
ldr x19, [sp,16]
; FP LR:
ldp x29, x30, [sp], 32
ret
.LC0:
.string "f(%d)\n"

ARM64: GCC 4.9.1

14.8: GCC 4.9.1 -fno-inline


printing_function:
; printf():
mov w1, w0
; "f(%d)\n"
adrp x0, .LC0
add x0, x0, :lo12:.LC0
; :
b printf
main:

186
14. 14.
; FP LR :
stp x29, x30, [sp, 32]!
; :
add x29, sp, 0
; X19 :
str x19, [sp,16]
; W19 .
; 2:
mov w19, 2
.L3:
; printing_function():
mov w0, w19
; .
add w19, w19, 1
; W0 .
bl printing_function
; ?
cmp w19, 10
; , :
bne .L3
; 0
mov w0, 0
; X19:
ldr x19, [sp,16]
; FP LR:
ldp x29, x30, [sp], 32
ret
.LC0:
.string "f(%d)\n"

14.1.5. MIPS

14.9: GCC 4.4.5 (IDA)


main:

; IDA
; :
i = 0x10
saved_FP = 8
saved_RA = 4

; :
addiu $sp, 0x28
sw $ra, 0x28+saved_RA($sp)
sw $fp, 0x28+saved_FP($sp)
move $fp, $sp
; 2
li $v0, 2
sw $v0, 0x28+i($fp)
; . "BEQ $ZERO, $ZERO, loc_9C":
b loc_9C
or $at, $zero ; branch delay slot, NOP
#

loc_80: # CODE XREF: main+48


; printing_function():
lw $a0, 0x28+i($fp)
jal printing_function
or $at, $zero ; branch delay slot, NOP
; , :
lw $v0, 0x28+i($fp)
or $at, $zero ; NOP
addiu $v0, 1
sw $v0, 0x28+i($fp)

loc_9C: # CODE XREF: main+18


; , 10?

187
14. 14.
lw $v0, 0x28+i($fp)
or $at, $zero ; NOP
slti $v0, 0xA
; 10, loc_80 ( ):
bnez $v0, loc_80
or $at, $zero ; branch delay slot, NOP
; , 0:
move $v0, $zero
; :
move $sp, $fp
lw $ra, 0x28+saved_RA($sp)
lw $fp, 0x28+saved_FP($sp)
addiu $sp, 0x28
jr $ra
or $at, $zero ; branch delay slot, NOP

B. , (BEQ).

14.1.6. -

: i, .
i, . .
, . , , :
for (i=0; i<total_entries_to_process; i++)
_;

total_entries_to_process 0, .
.
, , ,
, Keil, Xcode (LLVM),
MSVC GCC .

14.2.
4 8 , SIMD3 ,
, .. , , .
#include <stdio.h>

void my_memcpy (unsigned char* dst, unsigned char* src, size_t cnt)
{
size_t i;
for (i=0; i<cnt; i++)
dst[i]=src[i];
};

14.2.1.

14.10: GCC 4.9 x64 (-Os)


my_memcpy:
; RDI =
; RSI =
; RDX =

; (i) 0
xor eax, eax
.L2:
; ? :
cmp rax, rdx
je .L5
3 Single instruction, multiple data

188
14. 14.
; RSI+i:
mov cl, BYTE PTR [rsi+rax]
; RDI+i:
mov BYTE PTR [rdi+rax], cl
inc rax ; i++
jmp .L2
.L5:
ret

14.11: GCC 4.9 ARM64 (-Os)


my_memcpy:
; X0 =
; X1 =
; X2 =

; (i) 0
mov x3, 0
.L2:
; ? :
cmp x3, x2
beq .L5
; X1+i:
ldrb w4, [x1,x3]
; X1+i:
strb w4, [x0,x3]
add x3, x3, 1 ; i++
b .L2
.L5:
ret

14.12: Keil 6/2013 ( Thumb)


my_memcpy PROC
; R0 =
; R1 =
; R2 =

PUSH {r4,lr}
; (i) 0
MOVS r3,#0
; -, :
B |L0.12|
|L0.6|
; R1+i:
LDRB r4,[r1,r3]
; R1+i:
STRB r4,[r0,r3]
; i++
ADDS r3,r3,#1
|L0.12|
; i<size?
CMP r3,r2
; ,
BCC |L0.6|
POP {r4,pc}
ENDP

14.2.2. ARM ARM

Keil ARM :

14.13: Keil 6/2013 ( ARM)


my_memcpy PROC
; R0 =
; R1 =
; R2 =

189
14. 14.

; (i) 0
MOV r3,#0
|L0.4|
; ?
CMP r3,r2
; " ",
; .. R2<R3 i<size.
; R1+i:
LDRBCC r12,[r1,r3]
; R1+i:
STRBCC r12,[r0,r3]
; i++
ADDCC r3,r3,#1
; " ".
; , i<size
; , (.. i>=size)
BCC |L0.4|
;
BX lr
ENDP

14.2.3. MIPS

14.14: GCC 4.4.5 (-Os) (IDA)


my_memcpy:
; , :
b loc_14
; (i) 0
; \$v0:
move $v0, $zero ; branch delay slot

loc_8: # CODE XREF: my_memcpy+1C


; $t0 $v1:
lbu $v1, 0($t0)
; (i):
addiu $v0, 1
; $a3
sb $v1, 0($a3)

loc_14: # CODE XREF: my_memcpy


; , (i) $v0 ("cnt" $a2)
sltu $v1, $v0, $a2
; :
addu $t0, $a1, $v0
; $t0 = $a1+$v0 = src+i
; , "cnt":
bnez $v1, loc_8
; (\$a3 = \$a0+\$v0 = dst+i):
addu $a3, $a0, $v0 ; branch delay slot
; , BNEZ
jr $ra
or $at, $zero ; branch delay slot, NOP

: LBU (Load Byte Unsigned) SB (Store Byte). ARM,


MIPS 32 . , x86.
, 32- . LBU
(Unsigned). , LB (Load Byte) 32- . SB
8 .

14.2.4.

GCC : 25.1.2 (. 435).

190
14. 14.
14.3.
2 9 :

14.15: x86
mov [counter], 2 ;
jmp check
body:
;
; -
;
add [counter], 1 ;
check:
cmp [counter], 9
jle body

3 :

14.16: x86
MOV [counter], 2 ;
JMP check
body:
;
; -
;
MOV REG, [counter] ;
INC REG
MOV [counter], REG
check:
CMP [counter], 9
JLE body

, :

14.17: x86
MOV EBX, 2 ;
JMP check
body:
;
; -
; EBX, !
INC EBX ;
check:
CMP EBX, 9
JLE body

14.18: x86
MOV [counter], 2 ;
JMP label_check
label_increment:
ADD [counter], 1 ;
label_check:
CMP [counter], 10
JGE exit
;
; -
;
JMP label_increment
exit:

, ,
. , , ,
:

191
14. 14.
14.19: x86
MOV REG, 2 ;
body:
;
; -
; REG, !
INC REG ;
CMP REG, 10
JL body

LOOP. , . , ,
:

14.20: x86
; 10 1
MOV ECX, 10
body:
;
; -
; ECX, !
LOOP body

ARM. R4 :

14.21: ARM
MOV R4, 2 ;
B check
body:
;
; -
; R4, !
ADD R4,R4, #1 ;
check:
CMP R4, #10
BLT body

14.4.

14.4.1. #1

LOOP ?

14.4.2. #2

, (14.1.1 (. 178)), -
, , [6..20].

14.4.3. #3

14.22: MSVC 2010


$SG2795 DB '%d', 0aH, 00H

_main PROC
push esi
push edi
mov edi, DWORD PTR __imp__printf
mov esi, 100
npad 3 ; align next label
$LL3@main:
push esi

192
14. 14.
push OFFSET $SG2795 ; '%d'
call edi
dec esi
add esp, 8
test esi, esi
jg SHORT $LL3@main
pop edi
xor eax, eax
pop esi
ret 0
_main ENDP

14.23: Keil 6/2013 ( ARM)


main PROC
PUSH {r4,lr}
MOV r4,#0x64
|L0.8|
MOV r1,r4
ADR r0,|L0.40|
BL __2printf
SUB r4,r4,#1
CMP r4,#0
MOVLE r0,#0
BGT |L0.8|
POP {r4,pc}
ENDP

|L0.40|
DCB "%d\n",0

14.24: Keil 6/2013 ( Thumb)


main PROC
PUSH {r4,lr}
MOVS r4,#0x64
|L0.4|
MOVS r1,r4
ADR r0,|L0.24|
BL __2printf
SUBS r4,r4,#1
CMP r4,#0
BGT |L0.4|
MOVS r0,#0
POP {r4,pc}
ENDP

DCW 0x0000
|L0.24|
DCB "%d\n",0

14.25: GCC 4.9 (ARM64)


main:
stp x29, x30, [sp, 32]!
add x29, sp, 0
stp x19, x20, [sp,16]
adrp x20, .LC0
mov w19, 100
add x20, x20, :lo12:.LC0
.L2:
mov w1, w19
mov x0, x20
bl printf
subs w19, w19, #1
bne .L2
ldp x19, x20, [sp,16]
ldp x29, x30, [sp], 32
ret
.LC0:

193
14. 14.
.string "%d\n"

14.26: GCC 4.4.5 (MIPS) (IDA)


main:

var_18 = 0x18
var_C = 0xC
var_8 = 8
var_4 = 4

lui $gp, (__gnu_local_gp >> 16)


addiu $sp, 0x28
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x28+var_4($sp)
sw $s1, 0x28+var_8($sp)
sw $s0, 0x28+var_C($sp)
sw $gp, 0x28+var_18($sp)
la $s1, $LC0 # "%d\n"
li $s0, 0x64 # 'd'

loc_28: # CODE XREF: main+40


lw $t9, (printf & 0xFFFF)($gp)
move $a1, $s0
move $a0, $s1
jalr $t9
addiu $s0, 1
lw $gp, 0x28+var_18($sp)
bnez $s0, loc_28
or $at, $zero
lw $ra, 0x28+var_4($sp)
lw $s1, 0x28+var_8($sp)
lw $s0, 0x28+var_C($sp)
jr $ra
addiu $sp, 0x28

$LC0: .ascii "%d\n"<0> # DATA XREF: main+1C

: G.1.7 (. 986).

14.4.4. #4

14.27: MSVC 2010


$SG2795 DB '%d', 0aH, 00H

_main PROC
push esi
push edi
mov edi, DWORD PTR __imp__printf
mov esi, 1
npad 3 ; align next label
$LL3@main:
push esi
push OFFSET $SG2795 ; '%d'
call edi
add esi, 3
add esp, 8
cmp esi, 100
jl SHORT $LL3@main
pop edi
xor eax, eax
pop esi
ret 0
_main ENDP

194
14. 14.
14.28: Keil 6/2013 ( ARM)
main PROC
PUSH {r4,lr}
MOV r4,#1
|L0.8|
MOV r1,r4
ADR r0,|L0.40|
BL __2printf
ADD r4,r4,#3
CMP r4,#0x64
MOVGE r0,#0
BLT |L0.8|
POP {r4,pc}
ENDP

|L0.40|
DCB "%d\n",0

14.29: Keil 6/2013 ( Thumb)


main PROC
PUSH {r4,lr}
MOVS r4,#1
|L0.4|
MOVS r1,r4
ADR r0,|L0.24|
BL __2printf
ADDS r4,r4,#3
CMP r4,#0x64
BLT |L0.4|
MOVS r0,#0
POP {r4,pc}
ENDP

DCW 0x0000
|L0.24|
DCB "%d\n",0

14.30: GCC 4.9 (ARM64)


main:
stp x29, x30, [sp, 32]!
add x29, sp, 0
stp x19, x20, [sp,16]
adrp x20, .LC0
mov w19, 1
add x20, x20, :lo12:.LC0
.L2:
mov w1, w19
mov x0, x20
add w19, w19, 3
bl printf
cmp w19, 100
bne .L2
ldp x19, x20, [sp,16]
ldp x29, x30, [sp], 32
ret
.LC0:
.string "%d\n"

14.31: GCC 4.4.5 (MIPS) (IDA)


main:

var_18 = 0x18
var_10 = 0x10
var_C = 0xC
var_8 = 8
var_4 = 4

195
14. 14.
lui $gp, (__gnu_local_gp >> 16)
addiu $sp, 0x28
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x28+var_4($sp)
sw $s2, 0x28+var_8($sp)
sw $s1, 0x28+var_C($sp)
sw $s0, 0x28+var_10($sp)
sw $gp, 0x28+var_18($sp)
la $s2, $LC0 # "%d\n"
li $s0, 1
li $s1, 0x64 # 'd'

loc_30: # CODE XREF: main+48


lw $t9, (printf & 0xFFFF)($gp)
move $a1, $s0
move $a0, $s2
jalr $t9
addiu $s0, 3
lw $gp, 0x28+var_18($sp)
bne $s0, $s1, loc_30
or $at, $zero
lw $ra, 0x28+var_4($sp)
lw $s2, 0x28+var_8($sp)
lw $s1, 0x28+var_C($sp)
lw $s0, 0x28+var_10($sp)
jr $ra
addiu $sp, 0x28

$LC0: .ascii "%d\n"<0> # DATA XREF: main+20

: G.1.8 (. 987).

196
15. - 15. -

15

15.1. strlen()
. strlen()1 while(). ,
MSVC:
int my_strlen (const char * str)
{
const char *eos = str;

while( *eos++ ) ;

return( eos str 1 );


}

int main()
{
// test
return my_strlen("hello!");
};

15.1.1. x86

MSVC

, :
_eos$ = 4 ; size = 4
_str$ = 8 ; size = 4
_strlen PROC
push ebp
mov ebp, esp
push ecx
mov eax, DWORD PTR _str$[ebp] ; "str"
mov DWORD PTR _eos$[ebp], eax ; "eos"
$LN2@strlen_:
mov ecx, DWORD PTR _eos$[ebp] ; ECX=eos

; , ECX EDX 32- ,

movsx edx, BYTE PTR [ecx]


mov eax, DWORD PTR _eos$[ebp] ; EAX=eos
add eax, 1 ; EAX
mov DWORD PTR _eos$[ebp], eax ; eax "eos"
test edx, edx ; EDX ?
je SHORT $LN1@strlen_ ; , EDX ,
jmp SHORT $LN2@strlen_ ;
$LN1@strlen_:

197
15. - 15. -
;

mov eax, DWORD PTR _eos$[ebp]


sub eax, DWORD PTR _str$[ebp]
sub eax, 1 ;
mov esp, ebp
pop ebp
ret 0
_strlen_ ENDP

: MOVSX TEST.
. MOVSX , - ,
, EDX. EDX 32-. MOVSX MOV with Sign-Extend. 8-
31- MOVSX , , , .
.
MSVC GCC char . , char, int (int
), -2 ( 0xFE) int,
0x000000FE, , int, , 254, -2. -2 int
0xFFFFFFFE. 0xFE char int
, . MOVSX.
. (30 (. 471)).
char EDX,
, DL. , . register allocator
.
TEST EDX, EDX. TEST (19 (. 316)).
EDX 0.

GCC

GCC 4.4.1:
public strlen
strlen proc near

eos = dword ptr 4


arg_0 = dword ptr 8

push ebp
mov ebp, esp
sub esp, 10h
mov eax, [ebp+arg_0]
mov [ebp+eos], eax

loc_80483F0:
mov eax, [ebp+eos]
movzx eax, byte ptr [eax]
test al, al
setnz al
add [ebp+eos], 1
test al, al
jnz short loc_80483F0
mov edx, [ebp+eos]
mov eax, [ebp+arg_0]
mov ecx, edx
sub ecx, eax
mov eax, ecx
sub eax, 1
leave
retn
strlen endp

MSVC, MOVZX, MOVSX. MOVZX MOV with Zero-Extend.


- 0. ,
, : xor eax, eax / mov al, [...].

198
15. - 15. -
, , : mov al, byte ptr [eax] / test al,
al , EAX . ,
. , ,
( ) .
SETNZ. , AL , test al, al
ZF 0, SETNZ, ZF==0 (NZ not zero) 1 AL. , AL , -
loc_80483F0. , ,
.

MSVC

MSVC 2012, (/Ox) :

15.1: MSVC 2012 /Ob0


_str$ = 8 ; size = 4
_strlen PROC
mov edx, DWORD PTR _str$[esp4] ; EDX >
mov eax, edx ; EAX
$LL2@strlen:
mov cl, BYTE PTR [eax] ; CL = *EAX
inc eax ; EAX++
test cl, cl ; CL==0?
jne SHORT $LL2@strlen ; ,
sub eax, edx ;
dec eax ; EAX
ret 0
_strlen ENDP

. ,
.
INC/ DEC -. .

199
15. - 15. -
MSVC + OllyDbg

() OllyDbg. :

. 15.1: OllyDbg:

, OllyDbg , , .
EAX, Follow in Dump , .
hello!. 1 , . OllyDbg ,
- , .

200
15. - 15. -
F8 ( , ) , :

. 15.2: OllyDbg:

, EAX .

201
15. - 15. -
F8 , :

. 15.3: OllyDbg:

, EAX , . EDX
. .

202
15. - 15. -
SUB :

. 15.4: OllyDbg: EAX

EAX 7. , hello! 6, -
7. strlen() .
.

GCC

GCC 4.4.1 ( -O3):


public strlen
strlen proc near

arg_0 = dword ptr 8

push ebp
mov ebp, esp
mov ecx, [ebp+arg_0]
mov eax, ecx

loc_8048418:
movzx edx, byte ptr [eax]
add eax, 1
test dl, dl
jnz short loc_8048418
not ecx
add eax, ecx
pop ebp
retn
strlen endp

GCC MSVC MOVZX.


, MOVZX mov dl, byte ptr [eax].
, GCC , char 32-
EDX , .
NOT. . ,
XOR ECX, 0ffffffffh. NOT ADD

203
15. - 15. -
. -. ECX,
str, .
. : (30 (. 471)).
, , , :
ecx=str;
eax=eos;
ecx=(ecx)1;
eax=eax+ecx
return eax

:
ecx=str;
eax=eos;
eax=eaxecx;
eax=eax1;
return eax

GCC , ? . , -
.

15.1.2. ARM

32- ARM

Xcode 4.6.3 (LLVM) ( ARM)

15.2: Xcode 4.6.3 (LLVM) ( ARM)


_strlen

eos = 8
str = 4

SUB SP, SP, #8 ; 8


STR R0, [SP,#8+str]
LDR R0, [SP,#8+str]
STR R0, [SP,#8+eos]

loc_2CB8 ; CODE XREF: _strlen+28


LDR R0, [SP,#8+eos]
ADD R1, R0, #1
STR R1, [SP,#8+eos]
LDRSB R0, [R0]
CMP R0, #0
BEQ loc_2CD4
B loc_2CB8
loc_2CD4 ; CODE XREF: _strlen+24
LDR R0, [SP,#8+eos]
LDR R1, [SP,#8+str]
SUB R0, R0, R1 ; R0=eosstr
SUB R0, R0, #1 ; R0=R01
ADD SP, SP, #8 ; 8
BX LR

LLVM . , -
. :
eos str. IDA var_8 var_4 eos str .
, str eos.
loc_2CB8 .
(LDR, ADD, STR) eos R0.
eos .

204
15. - 15. -
LDRSB R0, [R0] (Load Register Signed Byte) R0, -
32- (signed) R02 . MOVSX x86.
(signed), char .
(15.1.1 (. 198)) , x86.
, ARM 8- 16- , -
x86. , , x86 ,
16- 8086 8- 8080, ARM 32- RISC-. -
, ARM, 32- .
, LDRSB R0, . CMP BEQ ,
0. 0, . 0, .
eos str, ,
R0.
N.B. . R0-R3 scratch registers.
,
. , .
, .
(BX) LR.

Xcode 4.6.3 (LLVM) ( Thumb)

15.3: Xcode 4.6.3 (LLVM) ( Thumb)


_strlen
MOV R1, R0

loc_2DF6
LDRB.W R2, [R1],#1
CMP R2, #0
BNE loc_2DF6
MVNS R0, R0
ADD R0, R1
BX LR

LLVM , eos str ,


. str R0, eos R1.
LDRB.W R2, [R1],#1 R2 R1, (signed),
32- , . #1 Post-indexed addressing, ..
R1 .
: 28.2 (. 464).
CMP BNE3 . , 0.
MVNS4 ( , NOT x86) ADD eos str 1. ,
R0 = str + eos, , . ,
, (15.1.1 (. 203)).
, LLVM, GCC, , ( ).

Keil 6/2013 ( ARM)

15.4: Keil 6/2013 ( ARM)


_strlen
MOV R1, R0

loc_2C8
LDRB R2, [R1],#1
CMP R2, #0
SUBEQ R0, R1, R0
SUBEQ R0, R0, #1
2 Keil char , MSVC GCC.
3 (PowerPC, ARM) Branch if Not Equal
4 MoVe Not

205
15. - 15. -
BNE loc_2C8
BX LR

, , , str eos 1
, . -EQ ,
CMP . , R0 0,
SUBEQ R0.

ARM64

GCC (Linaro) 4.9

my_strlen:
mov x1, x0
; X1 (eos), ,
.L58:
; X1 W2, X1 (-)
ldrb w2, [x1],1
; Compare and Branch if NonZero: W0 , .L58
cbnz w2, .L58
; X0 X1
sub x0, x1, x0
; 32-
sub w0, w0, #1
ret

15.1.1 (. 199): , ,
1 . .
, : my_strlen() 32- int,
size_t 64- .
, , strlen() , 4GB,
64- 64- . - ,
SUB 32- , SUB
64- ( ). , ,
, .

GCC (Linaro) 4.9

my_strlen:
;
sub sp, sp, #32
; (str) [sp,8]
str x0, [sp,8]
ldr x0, [sp,8]
; "str" "eos"
str x0, [sp,24]
nop
.L62:
; eos++
ldr x0, [sp,24] ; "eos" X0
add x1, x0, 1 ; X0
str x1, [sp,24] ; X0 "eos"
; X0 W0
ldrb w0, [x0]
; ? (WZR 32- )
cmp w0, wzr
; (Branch Not Equal)
bne .L62
; . .
; "eos" X1
ldr x1, [sp,24]
; "str" X0
ldr x0, [sp,8]
;

206
15. - 15. -
sub x0, x1, x0
;
sub w0, w0, #1
;
add sp, sp, 32
ret

. ( ). :
32- .

15.1.3. MIPS

15.5: GCC 4.4.5 (IDA)


my_strlen:
; "eos" $v1:
move $v1, $a0

loc_4:
; "eos" $a1:
lb $a1, 0($v1)
or $at, $zero ; load delay slot, NOP
; , loc_4:
bnez $a1, loc_4
; , "eos":
addiu $v1, 1 ; branch delay slot
; . "str":
nor $v0, $zero, $a0
; $v0=str1
jr $ra
; = $v1 + $v0 = eos + ( str1 ) = eos str 1
addu $v0, $v1, $v0 ; branch delay slot

MIPS NOT, NOR OR + NOT. -


5 , . NOT NOR DST, $ZERO, SRC.
30 (. 471), ,
1 . NOT str str 1.
.

15.2.

15.2.1. #1

15.6: MSVC 2010


_s$ = 8
_f PROC
mov edx, DWORD PTR _s$[esp4]
mov cl, BYTE PTR [edx]
xor eax, eax
test cl, cl
je SHORT $LN2@f
npad 4 ; align next label
$LL4@f:
cmp cl, 32
jne SHORT $LN3@f
inc eax
$LN3@f:
mov cl, BYTE PTR [edx+1]
inc edx
test cl, cl
5 NOR . , Apollo Guidance Computer -

5600 NOR: [Eic11].

207
15. - 15. -
jne SHORT $LL4@f
$LN2@f:
ret 0
_f ENDP

15.7: GCC 4.8.1 -O3


f:
.LFB24:
push ebx
mov ecx, DWORD PTR [esp+8]
xor eax, eax
movzx edx, BYTE PTR [ecx]
test dl, dl
je .L2
.L3:
cmp dl, 32
lea ebx, [eax+1]
cmove eax, ebx
add ecx, 1
movzx edx, BYTE PTR [ecx]
test dl, dl
jne .L3
.L2:
pop ebx
ret

15.8: Keil 6/2013 ( ARM)


f PROC
MOV r1,#0
|L0.4|
LDRB r2,[r0,#0]
CMP r2,#0
MOVEQ r0,r1
BXEQ lr
CMP r2,#0x20
ADDEQ r1,r1,#1
ADD r0,r0,#1
B |L0.4|
ENDP

15.9: Keil 6/2013 ( Thumb)


f PROC
MOVS r1,#0
B |L0.12|
|L0.4|
CMP r2,#0x20
BNE |L0.10|
ADDS r1,r1,#1
|L0.10|
ADDS r0,r0,#1
|L0.12|
LDRB r2,[r0,#0]
CMP r2,#0
BNE |L0.4|
MOVS r0,r1
BX lr
ENDP

15.10: GCC 4.9 (ARM64)


f:
ldrb w1, [x0]
cbz w1, .L4
mov w2, 0
.L3:
cmp w1, 32
ldrb w1, [x0,1]!

208
15. - 15. -
csinc w2, w2, w2, ne
cbnz w1, .L3
.L2:
mov w0, w2
ret
.L4:
mov w2, w1
b .L2

15.11: GCC 4.4.5 (MIPS) (IDA)


f:
lb $v1, 0($a0)
or $at, $zero
beqz $v1, locret_48
li $a1, 0x20 # ' '
b loc_28
move $v0, $zero
loc_18: # CODE XREF: f:loc_28
lb $v1, 0($a0)
or $at, $zero
beqz $v1, locret_40
or $at, $zero

loc_28: # CODE XREF: f+10


# f+38
bne $v1, $a1, loc_18
addiu $a0, 1
lb $v1, 0($a0)
or $at, $zero
bnez $v1, loc_28
addiu $v0, 1

locret_40: # CODE XREF: f+20


jr $ra
or $at, $zero
locret_48: # CODE XREF: f+8
jr $ra
move $v0, $zero

G.1.9 (. 987).

209
16. 16.

16

, . , ADD
SUB : 18 .52.1.
, . LEA, ,
: A.6.2 (. 965).

16.1.

16.1.1.

16.1: MSVC 2010


unsigned int f(unsigned int a)
{
return a*8;
};

8 , . , MSVC
, .
_TEXT SEGMENT
_a$ = 8 ; size = 4
_f PROC
; File c:\polygon\c\2.c
mov eax, DWORD PTR _a$[esp4]
add eax, eax
add eax, eax
add eax, eax
ret 0
_f ENDP
_TEXT ENDS
END

16.1.2.

2n .
unsigned int f(unsigned int a)
{
return a*4;
};

210
16. 16.
16.2: MSVC 2010
_a$ = 8 ; size = 4
_f PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _a$[ebp]
shl eax, 2
pop ebp
ret 0
_f ENDP

4 2 , 2 ( ).
3 100 .
:

7. 6 5 4 3 2 1 0

CF 7 6 5 4 3 2 1 0 0

.
4 ARM:

16.3: Keil 6/2013 ( ARM)


f PROC
LSL r0,r0,#2
BX lr
ENDP

4 MIPS:

16.4: GCC 4.4.5 (IDA)


jr $ra
sll $v0, $a0, 2 ; branch delay slot

SLL Shift Left Logical.

16.1.3. ,

, 7 17, .
.

32-

#include <stdint.h>

int f1(int a)
{
return a*7;
};

int f2(int a)
{
return a*28;
};

int f3(int a)
{
return a*17;
};

211
16. 16.
x86

16.5: MSVC 2012


; a*7
_a$ = 8
_f1 PROC
mov ecx, DWORD PTR _a$[esp4]
; ECX=a
lea eax, DWORD PTR [ecx*8]
; EAX=ECX*8
sub eax, ecx
; EAX=EAXECX=ECX*8ECX=ECX*7=a*7
ret 0
_f1 ENDP

; a*28
_a$ = 8
_f2 PROC
mov ecx, DWORD PTR _a$[esp4]
; ECX=a
lea eax, DWORD PTR [ecx*8]
; EAX=ECX*8
sub eax, ecx
; EAX=EAXECX=ECX*8ECX=ECX*7=a*7
shl eax, 2
; EAX=EAX<<2=(a*7)*4=a*28
ret 0
_f2 ENDP

; a*17
_a$ = 8
_f3 PROC
mov eax, DWORD PTR _a$[esp4]
; EAX=a
shl eax, 4
; EAX=EAX<<4=EAX*16=a*16
add eax, DWORD PTR _a$[esp4]
; EAX=EAX+a=a*16+a=a*17
ret 0
_f3 ENDP

ARM

Keil, ARM, ,
:

16.6: Keil 6/2013 ( ARM)


; a*7
||f1|| PROC
RSB r0,r0,r0,LSL #3
; R0=R0<<3R0=R0*8R0=a*8a=a*7
BX lr
ENDP

; a*28
||f2|| PROC
RSB r0,r0,r0,LSL #3
; R0=R0<<3R0=R0*8R0=a*8a=a*7
LSL r0,r0,#2
; R0=R0<<2=R0*4=a*7*4=a*28
BX lr
ENDP

; a*17
||f3|| PROC
ADD r0,r0,r0,LSL #4

212
16. 16.
; R0=R0+R0<<4=R0+R0*16=R0*17=a*17
BX lr
ENDP

Thumb . f2():

16.7: Keil 6/2013 ( Thumb)


; a*7
||f1|| PROC
LSLS r1,r0,#3
; R1=R0<<3=a<<3=a*8
SUBS r0,r1,r0
; R0=R1R0=a*8a=a*7
BX lr
ENDP

; a*28
||f2|| PROC
MOVS r1,#0x1c ; 28
; R1=28
MULS r0,r1,r0
; R0=R1*R0=28*a
BX lr
ENDP

; a*17
||f3|| PROC
LSLS r1,r0,#4
; R1=R0<<4=R0*16=a*16
ADDS r0,r0,r1
; R0=R0+R1=a+a*16=a*17
BX lr
ENDP

MIPS

16.8: GCC 4.4.5 (IDA)


_f1:
sll $v0, $a0, 3
; $v0 = $a0<<3 = $a0*8
jr $ra
subu $v0, $a0 ; branch delay slot
; $v0 = $v0$a0 = $a0*8$a0 = $a0*7

_f2:
sll $v0, $a0, 5
; $v0 = $a0<<5 = $a0*32
sll $a0, 2
; $a0 = $a0<<2 = $a0*4
jr $ra
subu $v0, $a0 ; branch delay slot
; $v0 = $a0*32$a0*4 = $a0*28

_f3:
sll $v0, $a0, 4
; $v0 = $a0<<4 = $a0*16
jr $ra
addu $v0, $a0 ; branch delay slot
; $v0 = $a0*16+$a0 = $a0*17

64-

#include <stdint.h>

213
16. 16.
int64_t f1(int64_t a)
{
return a*7;
};

int64_t f2(int64_t a)
{
return a*28;
};

int64_t f3(int64_t a)
{
return a*17;
};

x64

16.9: MSVC 2012


; a*7
f1:
lea rax, [0+rdi*8]
; RAX=RDI*8=a*8
sub rax, rdi
; RAX=RAXRDI=a*8a=a*7
ret

; a*28
f2:
lea rax, [0+rdi*4]
; RAX=RDI*4=a*4
sal rdi, 5
; RDI=RDI<<5=RDI*32=a*32
sub rdi, rax
; RDI=RDIRAX=a*32a*4=a*28
mov rax, rdi
ret

; a*17
f3:
mov rax, rdi
sal rax, 4
; RAX=RAX<<4=a*16
add rax, rdi
; RAX=a*16+a=a*17
ret

ARM64

GCC 4.9 ARM64 :

16.10: GCC (Linaro) 4.9 ARM64


; a*7
f1:
lsl x1, x0, 3
; X1=X0<<3=X0*8=a*8
sub x0, x1, x0
; X0=X1X0=a*8a=a*7
ret

; a*28
f2:
lsl x1, x0, 5
; X1=X0<<5=a*32
sub x0, x1, x0, lsl 2

214
16. 16.
; X0=X1X0<<2=a*32a<<2=a*32a*4=a*28
ret

; a*17
f3:
add x0, x0, x0, lsl 4
; X0=X0+X0<<4=a+a*16=a*17
ret

16.2.

16.2.1.

, 4:
unsigned int f(unsigned int a)
{
return a/4;
};

(MSVC 2010):

16.11: MSVC 2010


_a$ = 8 ; size = 4
_f PROC
mov eax, DWORD PTR _a$[esp4]
shr eax, 2
ret 0
_f ENDP

SHR (SHift Right) 2 .


(.. ) . 2 . ,
.
SHR SHL, .

7. 6 5 4 3 2 1 0

0 7 6 5 4 3 2 1 0 CF

, , 23. 23
10 (3 ). 2 .

, , - , -
!

4 ARM:

16.12: Keil 6/2013 ( ARM)


f PROC
LSR r0,r0,#2
BX lr
ENDP

4 MIPS:

16.13: GCC 4.4.5 (IDA)


jr $ra
srl $v0, $a0, 2 ; branch delay slot

SRL Shift Right Logical.

215
16. 16.
16.3.

16.3.1. #2

16.14: MSVC 2010


_a$ = 8
_f PROC
mov ecx, DWORD PTR _a$[esp4]
lea eax, DWORD PTR [ecx*8]
sub eax, ecx
ret 0
_f ENDP

16.15: Keil 6/2013 ( ARM)


f PROC
RSB r0,r0,r0,LSL #3
BX lr
ENDP

16.16: Keil 6/2013 ( Thumb)


f PROC
LSLS r1,r0,#3
SUBS r0,r1,r0
BX lr
ENDP

16.17: GCC 4.9 (ARM64)


f:
lsl w1, w0, 3
sub w0, w1, w0
ret

16.18: GCC 4.4.5 (MIPS) (IDA)


f:
sll $v0, $a0, 3
jr $ra
subu $v0, $a0

G.1.10 (. 987).

216
17. FPU 17. FPU

17

FPU

FPU .
CPU.

17.1. IEEE 754


IEEE 754 , 1 .

17.2. x86
FPU x86 2
Forth3 .
, ( 80486) ,
, . 4 . 80486 DX
FPU.
FWAIT, CPU , FPU
. , FPU- .. escape- (D8..DF)
, .
FPU 80- : ST(0)..ST(7). , IDA OllyDbg ST(0) ST,
Stack Top ( ).
IEEE 7545 .

17.3. ARM, MIPS, x86/x64 SIMD


ARM MIPS FPU , . SIMD
x86/x64.

17.4. /++
/++ : oat ( 6 ,
32 ) 7 double ( 8 , 64 ).
1 signicand fraction
2 wikipedia.org/wiki/Stack_machine
3 wikipedia.org/wiki/Forth_(programming_language)
4 , Doom (ru.wikipedia.org/wiki/___),

32- GPR (16 16 ), Doom 32- FPU, .. 80386


80486 SX.
5 wikipedia.org/wiki/IEEE_oating_point
6 wikipedia.org/wiki/Single-precision_oating-point_format
7 oat (21.6.2

(. 390)).
8 wikipedia.org/wiki/Double-precision_oating-point_format

217
17. FPU 17. FPU
GCC long double (extended precision9 , 80 ), MSVC .
, oat , int 32- , ,
, .

17.5.
:
#include <stdio.h>

double f (double a, double b)


{
return a/3.14 + b*4.1;
};

int main()
{
printf ("%f\n", f(1.2, 3.4));
};

17.5.1. x86

MSVC

MSVC 2010:

17.1: MSVC 2010: f()


CONST SEGMENT
__real@4010666666666666 DQ 04010666666666666r ; 4.1
CONST ENDS
CONST SEGMENT
__real@40091eb851eb851f DQ 040091eb851eb851fr ; 3.14
CONST ENDS
_TEXT SEGMENT
_a$ = 8 ; size = 8
_b$ = 16 ; size = 8
_f PROC
push ebp
mov ebp, esp
fld QWORD PTR _a$[ebp]

; : ST(0) = _a

fdiv QWORD PTR __real@40091eb851eb851f

; : ST(0) = _a 3.14

fld QWORD PTR _b$[ebp]

; : ST(0) = _b; ST(1) = _a 3.14

fmul QWORD PTR __real@4010666666666666

; :
; ST(0) = _b 4.1;
; ST(1) = _a 3.14

faddp ST(1), ST(0)

; : ST(0) =

pop ebp
ret 0
9 wikipedia.org/wiki/Extended_precision

218
17. FPU 17. FPU
_f ENDP

FLD 8 ST(0), 80-


(extended precision).
FDIV ST(0) , __real@40091eb851eb851f
3,14. ,
3,14 IEEE 754.
FDIV ST(0) .
, FDIVP, ST(1) ST(0), -
. Forth10 , 11 .
FLD b.
ST(1) , ST(0) b.
FMUL b ST(0) __real@4010666666666666 4,1
ST(0).
FADDP ST(1) ,
ST(0). ST(0).
ST(0), , .

10 wikipedia.org/wiki/Forth_(programming_language)
11 wikipedia.org/wiki/Stack_machine

219
17. FPU 17. FPU
MSVC + OllyDbg

2 32- . IEEE 754,


main(). , FLD 1,2 ST(0):

. 17.1: OllyDbg: FLD

- 64- IEEE 754 80- ( FPU),


1,1999, 1,2. EIP (FDIV),
. , OllyDbg : 3,14.

220
17. FPU 17. FPU
. FDIV , ST(0) 0,382 (quotient):

. 17.2: OllyDbg: FDIV

221
17. FPU 17. FPU
: FLD , ST(0) 3,4 ( 3,39999) :

. 17.3: OllyDbg: FLD

quotient ST(1). EIP : FMUL. 4,1


, OllyDbg .

222
17. FPU 17. FPU
: FMUL , ST(0) :

. 17.4: OllyDbg: FMUL

223
17. FPU 17. FPU
: FADDP , ST(0) , ST(1) :

. 17.5: OllyDbg: FADDP

ST(0) ST(0). main()


.
- : 13,93 ST(7). ?
, FPU : 17.2 (. 217). . ,
, . ( ) ,
7 ( ) , .
FPU 8 ( TOP), ,
. TOP ,
. .
. (, , ,
). . , FADDP ,
. , TOP.
, FPU .

GCC

GCC 4.4.1 ( -O3) , :

17.2: GCC 4.4.1


public f
f proc near

arg_0 = qword ptr 8


arg_8 = qword ptr 10h

push ebp
fld ds:dbl_8048608 ; 3.14

; : ST(0) = 3.14

224
17. FPU 17. FPU

mov ebp, esp


fdivr [ebp+arg_0]

; : ST(0) =

fld ds:dbl_8048610 ; 4.1

; : ST(0) = 4.1, ST(1) =

fmul [ebp+arg_8]

; : ST(0) = , ST(1) =

pop ebp
faddp st(1), st

; : ST(0) =

retn
f endp

, 3,14 ( ST(0)), arg_0 ,


ST(0).
FDIVR Reverse Divide , . -
, ( ),
FMUL -R .
FADDP , . ST(0)
.

17.5.2. ARM: Xcode 4.6.3 (LLVM) ( ARM)

ARM , -
. VFP (Vector Floating Point).
x86 , FPU-, , .

17.3: Xcode 4.6.3 (LLVM) ( ARM)


f
VLDR D16, =3.14
VMOV D17, R0, R1 ; "a"
VMOV D18, R2, R3 ; "b"
VDIV.F64 D16, D17, D16 ; a/3.14
VLDR D17, =4.1
VMUL.F64 D17, D18, D17 ; b*4.1
VADD.F64 D16, D17, D16 ; +
VMOV R0, R1, D16
BX LR

dbl_2C98 DCFD 3.14 ; DATA XREF: f


dbl_2CA0 DCFD 4.1 ; DATA XREF: f+10

, D. 64- . 32 -
(double) SIMD ( ARM NEON).
32 32- S-. (oat).
: D- double-, S- single-. -
: B.3.3 (. 976).
(3,14 4,1) IEEE 754.
VLDR VMOV, , LDR MOV, D-.
, , D-, ,
SIMD (NEON), .
R-, , ,
64 , R-.
VMOV D17, R0, R1 32- R0 R1 64- D17.

225
17. FPU 17. FPU
VMOV R0, R1, D16 : D16 R0 R1,
, 64 , R0 R1.
VDIV, VMUL VADD, , , , ,
.
Thumb-2 .

17.5.3. ARM: Keil 6/2013 ( Thumb)

f
PUSH {R3R7,LR}
MOVS R7, R2
MOVS R4, R3
MOVS R5, R0
MOVS R6, R1
LDR R2, =0x66666666 ; 4.1
LDR R3, =0x40106666
MOVS R0, R7
MOVS R1, R4
BL __aeabi_dmul
MOVS R7, R0
MOVS R4, R1
LDR R2, =0x51EB851F ; 3.14
LDR R3, =0x40091EB8
MOVS R0, R5
MOVS R1, R6
BL __aeabi_ddiv
MOVS R2, R7
MOVS R3, R4
BL __aeabi_dadd
POP {R3R7,PC}

; 4.1 IEEE 754:


dword_364 DCD 0x66666666 ; DATA XREF: f+A
dword_368 DCD 0x40106666 ; DATA XREF: f+C
; 3.14 IEEE 754:
dword_36C DCD 0x51EB851F ; DATA XREF: f+1A
dword_370 DCD 0x40091EB8 ; DATA XREF: f+1C

Keil , FPU NEON.


R-, FPU-
__aeabi_dmul, __aeabi_ddiv, __aeabi_dadd, , -
. , FPU-, , .
, x86 -
.
FPU- ARM soft oat armel (emulation), FPU- -
hard oat armhf.

17.5.4. ARM64: GCC (Linaro) 4.9

17.4: GCC (Linaro) 4.9


f:
; D0 = a, D1 = b
ldr d2, .LC25 ; 3.14
; D2 = 3.14
fdiv d0, d0, d2
; D0 = D0/D2 = a/3.14
ldr d2, .LC26 ; 4.1
; D2 = 4.1
fmadd d0, d1, d2, d0
; D0 = D1*D2+D0 = b*4.1+a/3.14
ret

226
17. FPU 17. FPU
; IEEE 754:
.LC25:
.word 1374389535 ; 3.14
.word 1074339512
.LC26:
.word 1717986918 ; 4.1
.word 1074816614

17.5.5. ARM64: GCC (Linaro) 4.9

17.5: GCC (Linaro) 4.9


f:
sub sp, sp, #16
str d0, [sp,8] ; "a" Register Save Area
str d1, [sp] ; "b" Register Save Area
ldr x1, [sp,8]
; X1 = a
ldr x0, .LC25
; X0 = 3.14
fmov d0, x1
fmov d1, x0
; D0 = a, D1 = 3.14
fdiv d0, d0, d1
; D0 = D0/D1 = a/3.14

fmov x1, d0
; X1 = a/3.14
ldr x2, [sp]
; X2 = b
ldr x0, .LC26
; X0 = 4.1
fmov d0, x2
; D0 = b
fmov d1, x0
; D1 = 4.1
fmul d0, d0, d1
; D0 = D0*D1 = b*4.1

fmov x0, d0
; X0 = D0 = b*4.1
fmov d0, x1
; D0 = a/3.14
fmov d1, x0
; D1 = X0 = b*4.1
fadd d0, d0, d1
; D0 = D0+D1 = a/3.14 + b*4.1

fmov x0, d0 ; \
fmov d0, x0 ; /
add sp, sp, 16
ret
.LC25:
.word 1374389535 ; 3.14
.word 1074339512
.LC26:
.word 1717986918 ; 4.1
.word 1074816614

GCC . , -
( GMOV). , GCC 4.9
ARM64. ARM64 64- D- 64-.
double GPR . 32- CPU.
, , , -
FMADD.

227
17. FPU 17. FPU
17.5.6. MIPS

MIPS ( 4),
, FPU.
ARM, MIPS . 32 32- ($F0-$F31): C.1.2 (. 978).
64- double, 32- F-.

17.6: GCC 4.4.5 (IDA)


f:
; $f12$f13=A
; $f14$f15=B
lui $v0, (dword_C4 >> 16) ; ?
; 32- 3.14 $f0:
lwc1 $f0, dword_BC
or $at, $zero ; load delay slot, NOP
; 32- 3.14 $f1:
lwc1 $f1, $LC0
lui $v0, ($LC1 >> 16) ; ?
; A $f12$f13, 3.14 $f0$f1, :
div.d $f0, $f12, $f0
; $f0$f1=A/3.14
; 32- 4.1 $f2:
lwc1 $f2, dword_C4
or $at, $zero ; load delay slot, NOP
; 32- 4.1 $f3:
lwc1 $f3, $LC1
or $at, $zero ; load delay slot, NOP
; B $f14$f15, 4.1 $f2$f3, :
mul.d $f2, $f14, $f2
; $f2$f3=B*4.1
jr $ra
; 64- $f0$f1:
add.d $f0, $f2 ; branch delay slot, NOP

.rodata.cst8:000000B8 $LC0: .word 0x40091EB8 # DATA XREF: f+C


.rodata.cst8:000000BC dword_BC: .word 0x51EB851F # DATA XREF: f+4
.rodata.cst8:000000C0 $LC1: .word 0x40106666 # DATA XREF: f+10
.rodata.cst8:000000C4 dword_C4: .word 0x66666666 # DATA XREF: f

:
LWC1 32- ( 1 ). -
LWC1 L.D.
DIV.D, MUL.D, ADD.D , (.D -
, .S )
: LUI .
, 64- double $V0. .
- - , , 12 .

17.6.

#include <math.h>
#include <stdio.h>

int main ()
{
printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54));

return 0;
}

12 dennis(a)yurichev.com

228
17. FPU 17. FPU
17.6.1. x86

, (MSVC 2010):

17.7: MSVC 2010


CONST SEGMENT
__real@40400147ae147ae1 DQ 040400147ae147ae1r ; 32.01
__real@3ff8a3d70a3d70a4 DQ 03ff8a3d70a3d70a4r ; 1.54
CONST ENDS

_main PROC
push ebp
mov ebp, esp
sub esp, 8 ;
fld QWORD PTR __real@3ff8a3d70a3d70a4
fstp QWORD PTR [esp]
sub esp, 8 ;
fld QWORD PTR __real@40400147ae147ae1
fstp QWORD PTR [esp]
call _pow
add esp, 8 ; "" .

; 8 .
; ST(0)

fstp QWORD PTR [esp] ; ST(0) printf()


push OFFSET $SG2651
call _printf
add esp, 12
xor eax, eax
pop ebp
ret 0
_main ENDP

FLD FSTP FPU- . pow()13


FPU- ST(0). printf() 8 double.
, MOV:
IEEE 754, pow() , .
, ARM: 17.6.2 (. 229).

17.6.2. ARM + Xcode 4.6.3 (LLVM) ( Thumb-2)

_main

var_C = 0xC

PUSH {R7,LR}
MOV R7, SP
SUB SP, SP, #4
VLDR D16, =32.01
VMOV R0, R1, D16
VLDR D16, =1.54
VMOV R2, R3, D16
BLX _pow
VMOV D16, R0, R1
MOV R0, 0xFC1 ; "32.01 ^ 1.54 = %lf\n"
ADD R0, PC
VMOV R1, R2, D16
BLX _printf
MOVS R1, 0
STR R0, [SP,#0xC+var_C]
MOV R0, R1
ADD SP, SP, #4
POP {R7,PC}

13 ,

229
17. FPU 17. FPU
dbl_2F90 DCFD 32.01 ; DATA XREF: _main+6
dbl_2F98 DCFD 1.54 ; DATA XREF: _main+E

, 64- R-.
(, ), R-
D-.
, , _pow R0 R1, R2 R3. R0
R1. _pow D16, R1 R2, printf() -.

17.6.3. ARM + Keil 6/2013 ( ARM)

_main
STMFD SP!, {R4R6,LR}
LDR R2, =0xA3D70A4 ; y
LDR R3, =0x3FF8A3D7
LDR R0, =0xAE147AE1 ; x
LDR R1, =0x40400147
BL pow
MOV R4, R0
MOV R2, R4
MOV R3, R1
ADR R0, a32_011_54Lf ; "32.01 ^ 1.54 = %lf\n"
BL __2printf
MOV R0, #0
LDMFD SP!, {R4R6,PC}

y DCD 0xA3D70A4 ; DATA XREF: _main+4


dword_520 DCD 0x3FF8A3D7 ; DATA XREF: _main+8
; double x
x DCD 0xAE147AE1 ; DATA XREF: _main+C
dword_528 DCD 0x40400147 ; DATA XREF: _main+10
a32_011_54Lf DCB "32.01 ^ 1.54 = %lf",0xA,0
; DATA XREF: _main+24

D-, R-.

17.6.4. ARM64 + GCC (Linaro) 4.9

17.8: GCC (Linaro) 4.9


f:
stp x29, x30, [sp, 16]!
add x29, sp, 0
ldr d1, .LC1 ; 1.54 D1
ldr d0, .LC0 ; 32.01 D0
bl pow
; pow() D0
adrp x0, .LC2
add x0, x0, :lo12:.LC2
bl printf
mov w0, 0
ldp x29, x30, [sp], 16
ret
.LC0:
; 32.01 IEEE 754
.word 1374389535
.word 1077936455
.LC1:
; 1.54 IEEE 754
.word 171798692
.word 1073259479
.LC2:
.string "32.01 ^ 1.54 = %lf\n"

230
17. FPU 17. FPU
D0 D1: pow() . D0 pow().
printf() , printf()
X-, D-.

17.6.5. MIPS

17.9: GCC 4.4.5 (IDA)


main:

var_10 = 0x10
var_4 = 4

; :
lui $gp, (dword_9C >> 16)
addiu $sp, 0x20
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x20+var_4($sp)
sw $gp, 0x20+var_10($sp)
lui $v0, (dword_A4 >> 16) ; ?
; 32- 32.01:
lwc1 $f12, dword_9C
; pow():
lw $t9, (pow & 0xFFFF)($gp)
; 32- 32.01:
lwc1 $f13, $LC0
lui $v0, ($LC1 >> 16) ; ?
; 32- 1.54:
lwc1 $f14, dword_A4
or $at, $zero ; load delay slot, NOP
; 32- 1.54:
lwc1 $f15, $LC1
; pow():
jalr $t9
or $at, $zero ; branch delay slot, NOP
lw $gp, 0x20+var_10($sp)
; $f0 $f1 $a3 $a2:
mfc1 $a3, $f0
lw $t9, (printf & 0xFFFF)($gp)
mfc1 $a2, $f1
; printf():
lui $a0, ($LC2 >> 16) # "32.01 ^ 1.54 = %lf\n"
jalr $t9
la $a0, ($LC2 & 0xFFFF) # "32.01 ^ 1.54 = %lf\n"
; :
lw $ra, 0x20+var_4($sp)
; 0:
move $v0, $zero
jr $ra
addiu $sp, 0x20

.rodata.str1.4:00000084 $LC2: .ascii "32.01 ^ 1.54 = %lf\n"<0>

; 32.01:
.rodata.cst8:00000098 $LC0: .word 0x40400147 # DATA XREF: main+20
.rodata.cst8:0000009C dword_9C: .word 0xAE147AE1 # DATA XREF: main
.rodata.cst8:0000009C # main+18
; 1.54:
.rodata.cst8:000000A0 $LC1: .word 0x3FF8A3D7 # DATA XREF: main+24
.rodata.cst8:000000A0 # main+30
.rodata.cst8:000000A4 dword_A4: .word 0xA3D70A4 # DATA XREF: main+14

, LUI 32- double $V0. .


MFC1 (Move From Coprocessor 1) ( ). FPU -
1, 1 . -
CPU (GPR). pow() $A3 $A2
printf() 64- double.

231
17. FPU 17. FPU
17.7.
:
#include <stdio.h>

double d_max (double a, double b)


{
if (a>b)
return a;

return b;
};

int main()
{
printf ("%f\n", d_max (1.2, 3.4));
printf ("%f\n", d_max (5.6, 4));
};

, , , .

17.7.1. x86

MSVC

MSVC 2010:

17.10: MSVC 2010


PUBLIC _d_max
_TEXT SEGMENT
_a$ = 8 ; size = 8
_b$ = 16 ; size = 8
_d_max PROC
push ebp
mov ebp, esp
fld QWORD PTR _b$[ebp]

; : ST(0) = _b
; _b ( ST(0)) _a,

fcomp QWORD PTR _a$[ebp]

fnstsw ax
test ah, 5
jp SHORT $LN1@d_max

; a>b

fld QWORD PTR _a$[ebp]


jmp SHORT $LN2@d_max
$LN1@d_max:
fld QWORD PTR _b$[ebp]
$LN2@d_max:
pop ebp
ret 0
_d_max ENDP

, FLD _b ST(0).
FCOMP ST(0) , _a C3/ C2/ C0 FPU.
16- FPU.
FCOMP . FCOM,
, .

232
17. FPU 17. FPU
, Intel P614 , C3/ C2/ C0. ,
( , FPU - ).
Intel P6 FCOMI/ FCOMIP/ FUCOMI/ FUCOMIP, , -
ZF/ PF/ CF.
FNSTSW AX. C3/ C2/ C0 , , 14, 10,
8. AX, AH.
b > a , C3/ C2/ C0 : 0, 0, 0.
a > b, : 0, 0, 1.
a = b, : 1, 0, 0.
( ), : 1, 1, 1.
C3/ C2/ C0 AX:
14 10 9 8

C3 C2 C1 C0

C3/ C2/ C0 AH:


6 2 1 0

C3 C2 C1 C0

test ah, 515 C0 C2 ( 0 2), -


.
parity ag16 . .
1 . 0 .
Wikipedia17 :

One common reason to test the parity ag actually has nothing to do with parity. The FPU has four
condition ags (C0 to C3), but they can not be tested directly, and must instead be rst copied to the ags
register. When this happens, C0 is placed in the carry ag, C2 in the parity ag and C3 in the zero ag. The
C2 ag is set when e.g. incomparable oating point values (NaN or unsupported format) are compared with
the FUCOM instructions.

Wikipedia, FPU- .
PF 1, C0 C2 1 0. JP (jump if PF==1).
C3/ C2/ C0 , , JP
: b > a a = b ( C3 test ah, 5).
. , FLD _b ST(0), ,
_a .

C2?

C2 (NaN, ..), . ,
FPU-, , .

14 Intel P6 Pentium Pro, Pentium II,


15 5=101b
16
17 wikipedia.org/wiki/Parity_ag

233
17. FPU 17. FPU
OllyDbg: a=1,2 b=3,4

OllyDbg:

. 17.6: OllyDbg: FLD

: a = 1, 2 b = 3, 4 ( : 2 32- ). b (3,4)
ST(0). FCOMP. OllyDbg FCOMP,
.

234
17. FPU 17. FPU
FCOMP :

. 17.7: OllyDbg: FCOMP

condition- FPU: . ST(7). ,


: 17.5.1 (. 224).

235
17. FPU 17. FPU
FNSTSW :

. 17.8: OllyDbg: FNSTSW

, AX . , condition- . (OllyDbg -
FNSTSW FSTSW ).

236
17. FPU 17. FPU
TEST :

. 17.9: OllyDbg: TEST

PF . : 0 0, 0 . OllyDbg -
JP JPE18 . .

18 Jump Parity Even ( x86)

237
17. FPU 17. FPU
JPE , FLD ST(0) b (3,4):

. 17.10: OllyDbg: FLD

238
17. FPU 17. FPU
OllyDbg: a=5,6 b=-1

OllyDbg:

. 17.11: OllyDbg: FLD

: a = 5, 6 b = 4. b (-4) ST(0). FCOMP. OllyDbg


FCOMP, .

239
17. FPU 17. FPU
FCOMP :

. 17.12: OllyDbg: FCOMP

condition- FPU: , C0.

240
17. FPU 17. FPU
FNSTSW :

. 17.13: OllyDbg: FNSTSW

, AX 0x100: C0 16- .

241
17. FPU 17. FPU
TEST :

. 17.14: OllyDbg: TEST

PF . : 0x100 1, 1 . JPE .

242
17. FPU 17. FPU
JPE , FLD ST(0) a (5,6):

. 17.15: OllyDbg: FLD

MSVC 2010

17.11: MSVC 2010


_a$ = 8 ; size = 8
_b$ = 16 ; size = 8
_d_max PROC
fld QWORD PTR _b$[esp4]
fld QWORD PTR _a$[esp4]

; : ST(0) = _a, ST(1) = _b

fcom ST(1) ; _a ST(1) = (_b)


fnstsw ax
test ah, 65 ; 00000041H
jne SHORT $LN5@d_max
; ST(0) ST(1) ,
; _a
fstp ST(1)

; : ST(0) = _a

ret 0
$LN5@d_max:
; ST(0) ST(0) ,
; _b
fstp ST(0)

; : ST(0) = _b

243
17. FPU 17. FPU
ret 0
_d_max ENDP

FCOM FCOMP , . -
, . C3/ C2/ C0 :
a > b, C3/ C2/ C0 : 0, 0, 0.
b > a, : 0, 0, 1.
a = b, : 1, 0, 0.
test ah, 65 C3 C0. , a > b:
JNE . FSTP ST(1) ST(0) -
. , ST(0) ( _a) ST(1).
_a. . ST(0) _a
.
JNE : b > a a = b. ST(0) ST(0) (
). ,
ST(1) ( _b). . FPU
, .

244
17. FPU 17. FPU
OllyDbg: a=1,2 =3,4

FLD :

. 17.16: OllyDbg: FLD

FCOM: OllyDbg ST(0) ST(1) .

245
17. FPU 17. FPU
FCOM :

. 17.17: OllyDbg: FCOM

C0 , .

246
17. FPU 17. FPU
FNSTSW , AX=0x3100:

. 17.18: OllyDbg: FNSTSW

247
17. FPU 17. FPU
TEST :

. 17.19: OllyDbg: TEST

ZF=0, .

248
17. FPU 17. FPU
FSTP ST ( FSTP ST(0)) 1,2 , 3,4:

. 17.20: OllyDbg: FSTP

, FSTP ST FPU-.

249
17. FPU 17. FPU
OllyDbg: a=5,6 b=-4

FLD :

. 17.21: OllyDbg: FLD

FCOM.

250
17. FPU 17. FPU
FCOM :

. 17.22: OllyDbg: FCOM

condition- .

251
17. FPU 17. FPU
FNSTSW , AX=0x3000:

. 17.23: OllyDbg: FNSTSW

252
17. FPU 17. FPU
TEST :

. 17.24: OllyDbg: TEST

ZF=1, .

253
17. FPU 17. FPU
FSTP ST(1) : FPU- 5,6.

. 17.25: OllyDbg: FSTP

, FSTP ST(1) : , ST(1).

GCC 4.4.1

17.12: GCC 4.4.1


d_max proc near

b = qword ptr 10h


a = qword ptr 8
a_first_half = dword ptr 8
a_second_half = dword ptr 0Ch
b_first_half = dword ptr 10h
b_second_half = dword ptr 14h

push ebp
mov ebp, esp
sub esp, 10h

; a b :

mov eax, [ebp+a_first_half]


mov dword ptr [ebp+a], eax
mov eax, [ebp+a_second_half]
mov dword ptr [ebp+a+4], eax
mov eax, [ebp+b_first_half]
mov dword ptr [ebp+b], eax
mov eax, [ebp+b_second_half]
mov dword ptr [ebp+b+4], eax

; a b FPU:

254
17. FPU 17. FPU
fld [ebp+a]
fld [ebp+b]

; : ST(0) b; ST(1) a

fxch st(1) ; ST(1) ST(0)

; : ST(0) a; ST(1) b

fucompp ; a b , .. a b
fnstsw ax ; FPU AX
sahf ; SF, ZF, AF, PF, CF AH
setnbe al ; 1 AL, CF=0 ZF=0
test al, al ; AL==0 ?
jz short loc_8048453 ;
fld [ebp+a]
jmp short locret_8048456

loc_8048453:
fld [ebp+b]

locret_8048456:
leave
retn
d_max endp

FUCOMPP FCOM, ,
-.
-.
FPU , NaN19 .
, , . .
, -
, .
, FCOM - . FUCOM
.
SAHF (Store AH into Flags) , FPU. 8 AH
8 :
7 6 4 2 0

SF ZF AF PF CF

, FNSTSW C3/ C2/ C0 AH, 6, 2,


0 AH:
6 2 1 0

C3 C2 C1 C0

, fnstsw ax / sahf C3/ C2/ C0 ZF, PF, CF.


, C3/ C2/ C0 :
a b , C3/ C2/ C0 : 0, 0, 0.
a b, : 0, 0, 1.
a = b, : 1, 0, 0.
, FUCOMPP/ FNSTSW/ SAHF :
a > b , : ZF=0, PF=0, CF=0.
a < b, : ZF=0, PF=0, CF=1.
a = b, : ZF=1, PF=0, CF=0.
SETNBE AL . JNBE,
, SETcc20 1 0 AL, Jcc . SETNBE 1
CF=0 ZF=0. , 0 AL.
CF 0 ZF 0 : a > b.
19 ru.wikipedia.org/wiki/NaN
20 cc condition code

255
17. FPU 17. FPU
AL 1, JZ _a.
, _b.

GCC 4.4.1

17.13: GCC 4.4.1


public d_max
d_max proc near

arg_0 = qword ptr 8


arg_8 = qword ptr 10h

push ebp
mov ebp, esp
fld [ebp+arg_0] ; _a
fld [ebp+arg_8] ; _b

; : ST(0) = _b, ST(1) = _a


fxch st(1)

; : ST(0) = _a, ST(1) = _b


fucom st(1) ; _a _b
fnstsw ax
sahf
ja short loc_8048448

; ST(0) ST(0) ( ), ,
; _b
fstp st
jmp short loc_804844A

loc_8048448:
; _a ST(0), , _a
fstp st(1)

loc_804844A:
pop ebp
retn
d_max endp

, , : JA SAHF. ,
, ( JA, JAE, JBE, JBE, JE/ JZ,
JNA, JNAE, JNB, JNBE, JNE/ JNZ) CF ZF.

, C3/ C2/ C0 AH FSTSW/ FNSTSW:


6 2 1 0

C3 C2 C1 C0

, AH CPU SAHF:
7 6 4 2 0

SF ZF AF PF CF

C3 C0 ZF CF ,
. JA , CF ZF .
, FNSTSW/ SAHF.
, FPU C3/ C2/ C0 , -
?

GCC 4.8.1 -O3

P6 Intel FPU-21 . FUCOMI (


CPU) FCMOVcc ( CMOVcc, FPU). , GCC
P6 ( Pentium, 80486, etc.) .
21 Pentium Pro, Pentium-II, ..

256
17. FPU 17. FPU
, FPU P6, CPU -
FPU.
:

17.14: GCC 4.8.1


fld QWORD PTR [esp+4] ; "a"
fld QWORD PTR [esp+12] ; "b"
; ST0=b, ST1=a
fxch st(1)
; ST0=a, ST1=b
; "a" "b"
fucomi st, st(1)
; ST1 ( "b") ST0 a<=b
; , "a" ST0
fcmovbe st, st(1)
; ST1
fstp st(1)
ret

, FXCH ( ). -
FLD FCMOVBE (below or equal ) FCMOVA (above ). ,
.
FUCOMI ST(0) (a) ST(1) (b) CPU. FCMOVBE
ST(1) ( b) ST(0) ( a) ST 0(a) <= ST 1(b). (a > b),
a ST(0).
FSTP ST(0) , ST(1).
GDB:

17.15: GCC 4.8.1 and GDB


1 dennis@ubuntuvm:~/polygon$ gcc O3 d_max.c o d_max fnoinline
2 dennis@ubuntuvm:~/polygon$ gdb d_max
3 GNU gdb (GDB) 7.6.1ubuntu
4 Copyright (C) 2013 Free Software Foundation, Inc.
5 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
6 This is free software: you are free to change and redistribute it.
7 There is NO WARRANTY, to the extent permitted by law. Type "show copying"
8 and "show warranty" for details.
9 This GDB was configured as "i686linuxgnu".
10 For bug reporting instructions, please see:
11 <http://www.gnu.org/software/gdb/bugs/>...
12 Reading symbols from /home/dennis/polygon/d_max...(no debugging symbols found)...done.
13 (gdb) b d_max
14 Breakpoint 1 at 0x80484a0
15 (gdb) run
16 Starting program: /home/dennis/polygon/d_max
17
18 Breakpoint 1, 0x080484a0 in d_max ()
19 (gdb) ni
20 0x080484a4 in d_max ()
21 (gdb) disas $eip
22 Dump of assembler code for function d_max:
23 0x080484a0 <+0>: fldl 0x4(%esp)
24 => 0x080484a4 <+4>: fldl 0xc(%esp)
25 0x080484a8 <+8>: fxch %st(1)
26 0x080484aa <+10>: fucomi %st(1),%st
27 0x080484ac <+12>: fcmovbe %st(1),%st
28 0x080484ae <+14>: fstp %st(1)
29 0x080484b0 <+16>: ret
30 End of assembler dump.
31 (gdb) ni
32 0x080484a8 in d_max ()
33 (gdb) info float
34 R7: Valid 0x3fff9999999999999800 +1.199999999999999956
35 =>R6: Valid 0x4000d999999999999800 +3.399999999999999911
36 R5: Empty 0x00000000000000000000
37 R4: Empty 0x00000000000000000000
38 R3: Empty 0x00000000000000000000

257
17. FPU 17. FPU
39 R2: Empty 0x00000000000000000000
40 R1: Empty 0x00000000000000000000
41 R0: Empty 0x00000000000000000000
42
43 Status Word: 0x3000
44 TOP: 6
45 Control Word: 0x037f IM DM ZM OM UM PM
46 PC: Extended Precision (64bits)
47 RC: Round to nearest
48 Tag Word: 0x0fff
49 Instruction Pointer: 0x73:0x080484a4
50 Operand Pointer: 0x7b:0xbffff118
51 Opcode: 0x0000
52 (gdb) ni
53 0x080484aa in d_max ()
54 (gdb) info float
55 R7: Valid 0x4000d999999999999800 +3.399999999999999911
56 =>R6: Valid 0x3fff9999999999999800 +1.199999999999999956
57 R5: Empty 0x00000000000000000000
58 R4: Empty 0x00000000000000000000
59 R3: Empty 0x00000000000000000000
60 R2: Empty 0x00000000000000000000
61 R1: Empty 0x00000000000000000000
62 R0: Empty 0x00000000000000000000
63
64 Status Word: 0x3000
65 TOP: 6
66 Control Word: 0x037f IM DM ZM OM UM PM
67 PC: Extended Precision (64bits)
68 RC: Round to nearest
69 Tag Word: 0x0fff
70 Instruction Pointer: 0x73:0x080484a8
71 Operand Pointer: 0x7b:0xbffff118
72 Opcode: 0x0000
73 (gdb) disas $eip
74 Dump of assembler code for function d_max:
75 0x080484a0 <+0>: fldl 0x4(%esp)
76 0x080484a4 <+4>: fldl 0xc(%esp)
77 0x080484a8 <+8>: fxch %st(1)
78 => 0x080484aa <+10>: fucomi %st(1),%st
79 0x080484ac <+12>: fcmovbe %st(1),%st
80 0x080484ae <+14>: fstp %st(1)
81 0x080484b0 <+16>: ret
82 End of assembler dump.
83 (gdb) ni
84 0x080484ac in d_max ()
85 (gdb) info registers
86 eax 0x1 1
87 ecx 0xbffff1c4 1073745468
88 edx 0x8048340 134513472
89 ebx 0xb7fbf000 1208225792
90 esp 0xbffff10c 0xbffff10c
91 ebp 0xbffff128 0xbffff128
92 esi 0x0 0
93 edi 0x0 0
94 eip 0x80484ac 0x80484ac <d_max+12>
95 eflags 0x203 [ CF IF ]
96 cs 0x73 115
97 ss 0x7b 123
98 ds 0x7b 123
99 es 0x7b 123
100 fs 0x0 0
101 gs 0x33 51
102 (gdb) ni
103 0x080484ae in d_max ()
104 (gdb) info float
105 R7: Valid 0x4000d999999999999800 +3.399999999999999911
106 =>R6: Valid 0x4000d999999999999800 +3.399999999999999911
107 R5: Empty 0x00000000000000000000
108 R4: Empty 0x00000000000000000000

258
17. FPU 17. FPU
109 R3: Empty 0x00000000000000000000
110 R2: Empty 0x00000000000000000000
111 R1: Empty 0x00000000000000000000
112 R0: Empty 0x00000000000000000000
113
114 Status Word: 0x3000
115 TOP: 6
116 Control Word: 0x037f IM DM ZM OM UM PM
117 PC: Extended Precision (64bits)
118 RC: Round to nearest
119 Tag Word: 0x0fff
120 Instruction Pointer: 0x73:0x080484ac
121 Operand Pointer: 0x7b:0xbffff118
122 Opcode: 0x0000
123 (gdb) disas $eip
124 Dump of assembler code for function d_max:
125 0x080484a0 <+0>: fldl 0x4(%esp)
126 0x080484a4 <+4>: fldl 0xc(%esp)
127 0x080484a8 <+8>: fxch %st(1)
128 0x080484aa <+10>: fucomi %st(1),%st
129 0x080484ac <+12>: fcmovbe %st(1),%st
130 => 0x080484ae <+14>: fstp %st(1)
131 0x080484b0 <+16>: ret
132 End of assembler dump.
133 (gdb) ni
134 0x080484b0 in d_max ()
135 (gdb) info float
136 =>R7: Valid 0x4000d999999999999800 +3.399999999999999911
137 R6: Empty 0x4000d999999999999800
138 R5: Empty 0x00000000000000000000
139 R4: Empty 0x00000000000000000000
140 R3: Empty 0x00000000000000000000
141 R2: Empty 0x00000000000000000000
142 R1: Empty 0x00000000000000000000
143 R0: Empty 0x00000000000000000000
144
145 Status Word: 0x3800
146 TOP: 7
147 Control Word: 0x037f IM DM ZM OM UM PM
148 PC: Extended Precision (64bits)
149 RC: Round to nearest
150 Tag Word: 0x3fff
151 Instruction Pointer: 0x73:0x080484ae
152 Operand Pointer: 0x7b:0xbffff118
153 Opcode: 0x0000
154 (gdb) quit
155 A debugging session is active.
156
157 Inferior 1 [process 30194] will be killed.
158
159 Quit anyway? (y or n) y
160 dennis@ubuntuvm:~/polygon$

ni, FLD .
FPU ( 33).
, FPU , (17.5.1 (. 224)). GDB
STx, FPU (Rx). ( 35) .
TOP Status Word ( 44). 6,
6.
a b FXCH ( 54).
FUCOMI ( 83). : CF ( 95).
FCMOVBE b (. 104).
FSTP ( 136). TOP 7, FPU- -
7.

259
17. FPU 17. FPU
17.7.2. ARM

Xcode 4.6.3 (LLVM) ( ARM)

17.16: Xcode 4.6.3 (LLVM) ( ARM)


VMOV D16, R2, R3 ; b
VMOV D17, R0, R1 ; a
VCMPE.F64 D17, D16
VMRS APSR_nzcv, FPSCR
VMOVGT.F64 D16, D17 ; "b" D16
VMOV R0, R1, D16
BX LR

. D17 D16 VCMPE.


x86, ARM (FPSCR22 ),
. , x86, ARM
, . VMRS, 4
(N, Z, C, V) ( APSR23 ).
VMOVGT MOVGT, D-, ,
(GT Greater Than).
, D16 b, D17.
D16 a.
VMOV , D16, R0 R1.

Xcode 4.6.3 (LLVM) ( Thumb-2)

17.17: Xcode 4.6.3 (LLVM) ( Thumb-2)


VMOV D16, R2, R3 ; b
VMOV D17, R0, R1 ; a
VCMPE.F64 D17, D16
VMRS APSR_nzcv, FPSCR
IT GT
VMOVGT.F64 D16, D17
VMOV R0, R1, D16
BX LR

, , . ,
ARM .
Thumb . 16- 4 ,
.
Thumb-2 Thumb- .
, IDA, VMOVGT, .
VMOV, IDA -GT ,
IT GT.
IT if-then block. -
, . IT GT ,
, GT (Greater Than) .
. , Angry Birds ( iOS):

17.18: Angry Birds Classic


...
ITE NE
VMOVNE R2, R3, D16
VMOVEQ R2, R3, D17
BLX _objc_msgSend ; not prefixed
...

22 (ARM) Floating-Point Status and Control Register


23 (ARM) Application Program Status Register

260
17. FPU 17. FPU
ITE if-then-else . ,
, ITE (NE, not equal) , .
( NE EQ (equal)).
VMOV ( VMOEQ) , (BLX).
, Angry Birds:

17.19: Angry Birds Classic


...
ITTTT EQ
MOVEQ R0, R4
ADDEQ SP, SP, #0x20
POPEQ.W {R8,R10}
POPEQ {R4R7,PC}
BLX ___stack_chk_fail ; not prefixed
...

T , -
. IDA -EQ.
, , ITEEE EQ (if-then-else-else-else),
:
EQ
NE
NE
NE

Angry Birds:

17.20: Angry Birds Classic


...
CMP.W R0, #0xFFFFFFFF
ITTE LE
SUBLE.W R10, R0, #1
NEGLE R0, R0
MOVGT R10, R0
MOVS R6, #0 ; not prefixed
CBZ R0, loc_1E7E32 ; not prefixed
...

ITTE (if-then-then-else) , , LE (Less or Equal) ,


(GT Greater Than).
. , Angry Birds (
classic iOS) IT: IT, ITE, ITT, ITTE, ITTT, ITTTT. ?
IDA ( ), 4
. , 16- (IT 0xBF), grep :
cat AngryBirdsClassic.lst | grep " BF" | grep "IT" > results.lst

, Thumb-2 , , -
IT , .

Xcode 4.6.3 (LLVM) ( ARM)

17.21: Xcode 4.6.3 (LLVM) ( ARM)


b = 0x20
a = 0x18
val_to_return = 0x10
saved_R7 = 4

STR R7, [SP,#saved_R7]!


MOV R7, SP
SUB SP, SP, #0x1C
BIC SP, SP, #7
VMOV D16, R2, R3

261
17. FPU 17. FPU
VMOV D17, R0, R1
VSTR D17, [SP,#0x20+a]
VSTR D16, [SP,#0x20+b]
VLDR D16, [SP,#0x20+a]
VLDR D17, [SP,#0x20+b]
VCMPE.F64 D16, D17
VMRS APSR_nzcv, FPSCR
BLE loc_2E08
VLDR D16, [SP,#0x20+a]
VSTR D16, [SP,#0x20+val_to_return]
B loc_2E10

loc_2E08
VLDR D16, [SP,#0x20+b]
VSTR D16, [SP,#0x20+val_to_return]

loc_2E10
VLDR D16, [SP,#0x20+val_to_return]
VMOV R0, R1, D16
MOV SP, R7
LDR R7, [SP+0x20+b],#4
BX LR

, , - a b, ,
.

Keil 6/2013 ( Thumb)

17.22: Keil 6/2013 ( Thumb)


PUSH {R3R7,LR}
MOVS R4, R2
MOVS R5, R3
MOVS R6, R0
MOVS R7, R1
BL __aeabi_cdrcmple
BCS loc_1C0
MOVS R0, R6
MOVS R1, R7
POP {R3R7,PC}

loc_1C0
MOVS R0, R4
MOVS R1, R5
POP {R3R7,PC}

Keil FPU-, , , -
. __aeabi_cdrcmple.

N.B. , BCS (Carry set


Greater than or equal) .

17.7.3. ARM64

GCC (Linaro) 4.9

d_max:
; D0 a, D1 b
fcmpe d0, d1
fcsel d0, d0, d1, gt
; D0
ret

ARM64 ISA FPU-, CPU APSR FPSCR . FPU


( ). FCMPE. , D0 D1
( ) APSR (N, Z, C, V).

262
17. FPU 17. FPU
FCSEL (Floating Conditional Select) D0 D1 D0 (GT Greater Than
), , APSR FPSCR. ,
, .
(GT), D0 D0 (.. ). ,
D1 D0.

GCC (Linaro) 4.9

d_max:
; "Register Save Area"
sub sp, sp, #16
str d0, [sp,8]
str d1, [sp]
;
ldr x1, [sp,8]
ldr x0, [sp]
fmov d0, x1
fmov d1, x0
; D0 a, D1 b
fcmpe d0, d1
ble .L76
; a>b; D0 (a) X0
ldr x0, [sp,8]
b .L74
.L76:
; a<=b; D1 (b) X0
ldr x0, [sp]
.L74:
; X0
fmov d0, x0
; D0
add sp, sp, 16
ret

GCC .
(Register Save Area). X0/ X1 D0/ D1 -
FCMPE. , . FCMPE
APSR. FCSEL,
: BLE (Branch if Less than or Equal (
)). (a > b) a X0. (a <= b) b X0.
, X0 D0, .

, ,
( FCSEL).

GCC (Linaro) 4.9 oat

. oat double.
float f_max (float a, float b)
{
if (a>b)
return a;

return b;
};

f_max:
; S0 a, S1 b
fcmpe s0, s1
fcsel s0, s0, s1, gt
; S0

263
17. FPU 17. FPU
ret

, S- D-. oat 32- S-


( 64- D-).

17.7.4. MIPS

MIPS , FPU -
CPU. MIPS ( FCC0), 8 ( FCC7-FCC0).
FCCR.

17.23: GCC 4.4.5 (IDA)


d_max:
; FPU 1, $f14<$f12 (b<a):
c.lt.d $f14, $f12
or $at, $zero ; NOP
; locret_14
bc1t locret_14
; ( "a"):
mov.d $f0, $f12 ; branch delay slot
; (.. b>=a)
; "b":
mov.d $f0, $f14

locret_14:
jr $ra
or $at, $zero ; branch delay slot, NOP

C.LT.D . LT Less Than ( ). D double.


, FCC0 .
BC1T FCC0 , . T
(True). BC1F , (False).
$F0.

17.8. ,
, 24 .
12 34 12, 34, .
, .

17.9. x64
, x86-64, : 27 (. 451).

17.10.

17.10.1. #1

FXCH 17.7.1 (. 256) .

17.10.2. #2

?
24 ru.wikipedia.org/wiki/__

264
17. FPU 17. FPU
17.24: MSVC 2010
__real@4014000000000000 DQ 04014000000000000r ; 5

_a1$ = 8 ; size = 8
_a2$ = 16 ; size = 8
_a3$ = 24 ; size = 8
_a4$ = 32 ; size = 8
_a5$ = 40 ; size = 8
_f PROC
fld QWORD PTR _a1$[esp4]
fadd QWORD PTR _a2$[esp4]
fadd QWORD PTR _a3$[esp4]
fadd QWORD PTR _a4$[esp4]
fadd QWORD PTR _a5$[esp4]
fdiv QWORD PTR __real@4014000000000000
ret 0
_f ENDP

17.25: Keil 6/2013 ( Thumb / Cortex-R4F CPU)


f PROC
VADD.F64 d0,d0,d1
VMOV.F64 d1,#5.00000000
VADD.F64 d0,d0,d2
VADD.F64 d0,d0,d3
VADD.F64 d2,d0,d4
VDIV.F64 d0,d2,d1
BX lr
ENDP

17.26: GCC 4.9 (ARM64)


f:
fadd d0, d0, d1
fmov d1, 5.0e+0
fadd d2, d0, d2
fadd d3, d2, d3
fadd d0, d3, d4
fdiv d0, d0, d1
ret

17.27: GCC 4.4.5 (MIPS) (IDA)


f:

arg_10 = 0x10
arg_14 = 0x14
arg_18 = 0x18
arg_1C = 0x1C
arg_20 = 0x20
arg_24 = 0x24

lwc1 $f0, arg_14($sp)


add.d $f2, $f12, $f14
lwc1 $f1, arg_10($sp)
lui $v0, ($LC0 >> 16)
add.d $f0, $f2, $f0
lwc1 $f2, arg_1C($sp)
or $at, $zero
lwc1 $f3, arg_18($sp)
or $at, $zero
add.d $f0, $f2
lwc1 $f2, arg_24($sp)
or $at, $zero
lwc1 $f3, arg_20($sp)
or $at, $zero
add.d $f0, $f2
lwc1 $f2, dword_6C
or $at, $zero
lwc1 $f3, $LC0

265
17. FPU 17. FPU
jr $ra
div.d $f0, $f2

$LC0: .word 0x40140000 # DATA XREF: f+C


# f+44
dword_6C: .word 0 # DATA XREF: f+3C

G.1.11 (. 987).

266
18. 18.

18

, 1 .

18.1.

#include <stdio.h>

int main()
{
int a[20];
int i;

for (i=0; i<20; i++)


a[i]=i*2;

for (i=0; i<20; i++)


printf ("a[%d]=%d\n", i, a[i]);

return 0;
};

18.1.1. x86

MSVC

18.1: MSVC 2008


_TEXT SEGMENT
_i$ = 84 ; size = 4
_a$ = 80 ; size = 80
_main PROC
push ebp
mov ebp, esp
sub esp, 84 ; 00000054H
mov DWORD PTR _i$[ebp], 0
jmp SHORT $LN6@main
$LN5@main:
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
$LN6@main:
cmp DWORD PTR _i$[ebp], 20 ; 00000014H
jge SHORT $LN4@main
mov ecx, DWORD PTR _i$[ebp]
shl ecx, 1
mov edx, DWORD PTR _i$[ebp]
1 AKA2

267
18. 18.
mov DWORD PTR _a$[ebp+edx*4], ecx
jmp SHORT $LN5@main
$LN4@main:
mov DWORD PTR _i$[ebp], 0
jmp SHORT $LN3@main
$LN2@main:
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
$LN3@main:
cmp DWORD PTR _i$[ebp], 20 ; 00000014H
jge SHORT $LN1@main
mov ecx, DWORD PTR _i$[ebp]
mov edx, DWORD PTR _a$[ebp+ecx*4]
push edx
mov eax, DWORD PTR _i$[ebp]
push eax
push OFFSET $SG2463
call _printf
add esp, 12 ; 0000000cH
jmp SHORT $LN2@main
$LN1@main:
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP

, . , . shl ecx, 1
ECX 2, (16.2.1 (. 215)).
80 , 20 4 .

268
18. 18.
OllyDbg.
, : 32- int, 2:

. 18.1: OllyDbg:

, 20 .

GCC

GCC 4.4.1:

18.2: GCC 4.4.1


public main
main proc near ; DATA XREF: _start+17

var_70 = dword ptr 70h


var_6C = dword ptr 6Ch
var_68 = dword ptr 68h
i_2 = dword ptr 54h
i = dword ptr 4

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 70h
mov [esp+70h+i], 0 ; i=0
jmp short loc_804840A

loc_80483F7:
mov eax, [esp+70h+i]
mov edx, [esp+70h+i]
add edx, edx ; edx=i*2

269
18. 18.
mov [esp+eax*4+70h+i_2], edx
add [esp+70h+i], 1 ; i++

loc_804840A:
cmp [esp+70h+i], 13h
jle short loc_80483F7
mov [esp+70h+i], 0
jmp short loc_8048441

loc_804841B:
mov eax, [esp+70h+i]
mov edx, [esp+eax*4+70h+i_2]
mov eax, offset aADD ; "a[%d]=%d\n"
mov [esp+70h+var_68], edx
mov edx, [esp+70h+i]
mov [esp+70h+var_6C], edx
mov [esp+70h+var_70], eax
call _printf
add [esp+70h+i], 1

loc_8048441:
cmp [esp+70h+i], 13h
jle short loc_804841B
mov eax, 0
leave
retn
main endp

a int* ( int).
, , ( -
). a[idx], idx
, , .
. string . const char[]. -
. : string[i]
/++!

18.1.2. ARM

Keil 6/2013 ( ARM)

EXPORT _main
_main
STMFD SP!, {R4,LR}
SUB SP, SP, #0x50 ; 20- int

MOV R4, #0 ; i
B loc_4A0
loc_494
MOV R0, R4,LSL#1 ; R0=R4*2
STR R0, [SP,R4,LSL#2] ; R0 SP+R4<<2 ( SP+R4*4)
ADD R4, R4, #1 ; i=i+1

loc_4A0
CMP R4, #20 ; i<20?
BLT loc_494 ; ,

MOV R4, #0 ; i
B loc_4C4
loc_4B0
LDR R2, [SP,R4,LSL#2] ; ( printf) R2=*(SP+R4<<4) ( *(SP+R4*4))
MOV R1, R4 ; ( printf) R1=i
ADR R0, aADD ; "a[%d]=%d\n"
BL __2printf

270
18. 18.
ADD R4, R4, #1 ; i=i+1

loc_4C4
CMP R4, #20 ; i<20?
BLT loc_4B0 ; ,
MOV R0, #0 ;
ADD SP, SP, #0x50 ; , 20
LDMFD SP!, {R4,PC}

int 32 ( 4 ), 20 int, 80 (0x50) .


SUB SP, SP, #0x50
.
i R4.
, , : i 2, 1 , -
MOV R0, R4,LSL#1 .
STR R0, [SP,R4,LSL#2] R0 . : SP
, R4 i. i 2 , 4 (
4 ) .
LDR R2, [SP,R4,LSL#2]. -
.

Keil 6/2013 ( Thumb)

_main
PUSH {R4,R5,LR}
; 20 int +
SUB SP, SP, #0x54

MOVS R0, #0 ; i
MOV R5, SP ;

loc_1CE
LSLS R1, R0, #1 ; R1=i<<1 ( i*2)
LSLS R2, R0, #2 ; R2=i<<2 ( i*4)
ADDS R0, R0, #1 ; i=i+1
CMP R0, #20 ; i<20?
STR R1, [R5,R2] ; R1 *(R5+R2) ( R5+i*4)
BLT loc_1CE ; , i<20,

MOVS R4, #0 ; i=0


loc_1DC
LSLS R0, R4, #2 ; R0=i<<2 ( i*4)
LDR R2, [R5,R0] ; *(R5+R0) ( R5+i*4)
MOVS R1, R4
ADR R0, aADD ; "a[%d]=%d\n"
BL __2printf
ADDS R4, R4, #1 ; i=i+1
CMP R4, #20 ; i<20?
BLT loc_1DC ; , i<20,
MOVS R0, #0 ;
; , 20- int
ADD SP, SP, #0x54
POP {R4,R5,PC}

Thumb . Thumb ( LSLS),


.
- , 4 .

GCC 4.9.1 (ARM64)

271
18. 18.
18.3: GCC 4.9.1 (ARM64)
.LC0:
.string "a[%d]=%d\n"
main:
; FP LR :
stp x29, x30, [sp, 112]!
; (FP=SP)
add x29, sp, 0
; 0 (WZR ):
str wzr, [x29,108]
; :
b .L2
.L3:
; "i":
ldr w0, [x29,108]
; 2:
lsl w2, w0, 1
; :
add x0, x29, 24
; 32- 64- :
ldrsw x1, [x29,108]
; (X0+X1<<2=array address+i*4) W2 (i*2) :
str w2, [x0,x1,lsl 2]
; (i):
ldr w0, [x29,108]
add w0, w0, 1
str w0, [x29,108]
.L2:
; , :
ldr w0, [x29,108]
cmp w0, 19
; L3 ( ), :
ble .L3
; .
; 0.
; ,
; (i) .
str wzr, [x29,108]
b .L4
.L5:
; :
add x0, x29, 24
; "i":
ldrsw x1, [x29,108]
; (X0+X1<<2 = + i*4)
ldr w2, [x0,x1,lsl 2]
; "a[%d]=%d\n" :
adrp x0, .LC0
add x0, x0, :lo12:.LC0
; "i" W1 printf() :
ldr w1, [x29,108]
; W2 .
; printf():
bl printf
; "i":
ldr w0, [x29,108]
add w0, w0, 1
str w0, [x29,108]
.L4:
; ?
ldr w0, [x29,108]
cmp w0, 19
; , :
ble .L5
; 0
mov w0, 0
; FP LR:
ldp x29, x30, [sp], 112
ret

272
18. 18.
18.1.3. MIPS

S-, . -
.
18.4: GCC 4.4.5 (IDA)
main:

var_70 = 0x70
var_68 = 0x68
var_14 = 0x14
var_10 = 0x10
var_C = 0xC
var_8 = 8
var_4 = 4
; :
lui $gp, (__gnu_local_gp >> 16)
addiu $sp, 0x80
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x80+var_4($sp)
sw $s3, 0x80+var_8($sp)
sw $s2, 0x80+var_C($sp)
sw $s1, 0x80+var_10($sp)
sw $s0, 0x80+var_14($sp)
sw $gp, 0x80+var_70($sp)
addiu $s1, $sp, 0x80+var_68
move $v1, $s1
move $v0, $zero
; .
; GCC :
li $a0, 0x28 # '('

loc_34: # CODE XREF: main+3C


; :
sw $v0, 0($v1)
; ( ) 2 :
addiu $v0, 2
; ?
bne $v0, $a0, loc_34
; , 4 :
addiu $v1, 4
;
;
la $s3, $LC0 # "a[%d]=%d\n"
; "i" $s0:
move $s0, $zero
li $s2, 0x14

loc_54: # CODE XREF: main+70


; printf():
lw $t9, (printf & 0xFFFF)($gp)
lw $a2, 0($s1)
move $a1, $s0
move $a0, $s3
jalr $t9
; "i":
addiu $s0, 1
lw $gp, 0x80+var_70($sp)
; , :
bne $s0, $s2, loc_54
; 32- :
addiu $s1, 4
;
lw $ra, 0x80+var_4($sp)
move $v0, $zero
lw $s3, 0x80+var_8($sp)
lw $s2, 0x80+var_C($sp)
lw $s1, 0x80+var_10($sp)
lw $s0, 0x80+var_14($sp)
jr $ra

273
18. 18.
addiu $sp, 0x80

$LC0: .ascii "a[%d]=%d\n"<0> # DATA XREF: main+44

: i, i 2 (
2 ) ( 4 ).
: ( $V0) 2 , ( $V1) 4.
printf(). i , ,
1 ( $S0), ( $S1) 4 .
, : 39 (. 500). ,
.

18.2.

18.2.1.

, []. ,
printf() , ? 20 ?
/++, , , .
, :
#include <stdio.h>

int main()
{
int a[20];
int i;

for (i=0; i<20; i++)


a[i]=i*2;

printf ("a[20]=%d\n", a[20]);

return 0;
};

(MSVC 2008):

18.5: MSVC 2008


$SG2474 DB 'a[20]=%d', 0aH, 00H

_i$ = 84 ; size = 4
_a$ = 80 ; size = 80
_main PROC
push ebp
mov ebp, esp
sub esp, 84
mov DWORD PTR _i$[ebp], 0
jmp SHORT $LN3@main
$LN2@main:
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
$LN3@main:
cmp DWORD PTR _i$[ebp], 20
jge SHORT $LN1@main
mov ecx, DWORD PTR _i$[ebp]
shl ecx, 1
mov edx, DWORD PTR _i$[ebp]
mov DWORD PTR _a$[ebp+edx*4], ecx
jmp SHORT $LN2@main
$LN1@main:
mov eax, DWORD PTR _a$[ebp+80]
push eax
push OFFSET $SG2474 ; 'a[20]=%d'

274
18. 18.
call DWORD PTR __imp__printf
add esp, 8
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END

. 18.2: OllyDbg:

-, , 80 .

275
18. 18.
OllyDbg, . , -
:

. 18.3: OllyDbg: 20- printf()

? , EBP.

276
18. 18.
, , :

. 18.4: OllyDbg: EBP

, ? - ,
, 3 ,
.

18.2.2.

, - , ?
:
#include <stdio.h>

int main()
{
int a[20];
int i;

for (i=0; i<30; i++)


a[i]=i;

return 0;
};

MSVC

:
3 Java, Python, ..

277
18. 18.
18.6: MSVC 2008
_TEXT SEGMENT
_i$ = 84 ; size = 4
_a$ = 80 ; size = 80
_main PROC
push ebp
mov ebp, esp
sub esp, 84
mov DWORD PTR _i$[ebp], 0
jmp SHORT $LN3@main
$LN2@main:
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
$LN3@main:
cmp DWORD PTR _i$[ebp], 30 ; 0000001eH
jge SHORT $LN1@main
mov ecx, DWORD PTR _i$[ebp]
mov edx, DWORD PTR _i$[ebp] ; . .
mov DWORD PTR _a$[ebp+ecx*4], edx ; ECX.
jmp SHORT $LN2@main
$LN1@main:
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP

, . . , .

278
18. 18.
OllyDbg, 30 :

. 18.5: OllyDbg: EBP

279
18. 18.
:

. 18.6: OllyDbg: EIP , OllyDbg 0x15

, .
EIP 0x15. , win32-! - , ,
. , EBP 0x14, ECX EDX 0x1D.
.
main(), EBP.
i 84 . (20+1)*sizeof(int). ESP _i
PUSH -, - _i.
main():
ESP 4 i
ESP+4 80 a[20]
ESP+84 EBP
ESP+88
a[19]=_ int ( !)
a[20]=_ _ EBP.
. 20-
20. , , EBP (20 -
0x14 ). RET,
POP EIP.
RET ( - CRT), main()),
21 , 0x15 . 0x15,
, .

280
18. 18.
! buffer overow 4 .
int ( char), , ,
, , ,
. , , 5 .

GCC

GCC 4.4.1. :
public main
main proc near

a = dword ptr 54h


i = dword ptr 4

push ebp
mov ebp, esp
sub esp, 60h ; 96
mov [ebp+i], 0
jmp short loc_80483D1
loc_80483C3:
mov eax, [ebp+i]
mov edx, [ebp+i]
mov [ebp+eax*4+a], edx
add [ebp+i], 1
loc_80483D1:
cmp [ebp+i], 1Dh
jle short loc_80483C3
mov eax, 0
leave
retn
main endp

Linux : Segmentation fault.


GDB, :
(gdb) r
Starting program: /home/dennis/RE/1

Program received signal SIGSEGV, Segmentation fault.


0x00000016 in ?? ()
(gdb) info registers
eax 0x0 0
ecx 0xd2f96388 755407992
edx 0x1d 29
ebx 0x26eff4 2551796
esp 0xbffff4b0 0xbffff4b0
ebp 0x15 0x15
esi 0x0 0
edi 0x0 0
eip 0x16 0x16
eflags 0x10202 [ IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)

, win32, .
4 wikipedia
5 : [One96]

281
18. 18.
18.3.
/++. MSVC
6 :
/RTCs Stack Frame runtime checking
/GZ Enable stack checks (/RTCs)


. ,
RET, ( ). , , .
7 , 8 .
, , .
, .
(18.1 (. 267)) MSVC RTC1 RTCs,
@_RTC_CheckStackVars@8, .
, GCC. alloca() (5.2.4 (. 28)):
#ifdef __GNUC__
#include <alloca.h> // GCC
#else
#include <malloc.h> // MSVC
#endif
#include <stdio.h>

void f()
{
char *buf=(char*)alloca (600);
#ifdef __GNUC__
snprintf (buf, 600, "hi! %d, %d, %d\n", 1, 2, 3); // GCC
#else
_snprintf (buf, 600, "hi! %d, %d, %d\n", 1, 2, 3); // MSVC
#endif

puts (buf);
};

, , GCC 4.7.3 :

18.7: GCC 4.7.3


.LC0:
.string "hi! %d, %d, %d\n"
f:
push ebp
mov ebp, esp
push ebx
sub esp, 676
lea ebx, [esp+39]
and ebx, 16
mov DWORD PTR [esp+20], 3
mov DWORD PTR [esp+16], 2
mov DWORD PTR [esp+12], 1
mov DWORD PTR [esp+8], OFFSET FLAT:.LC0 ; "hi! %d, %d, %d\n"
mov DWORD PTR [esp+4], 600
mov DWORD PTR [esp], ebx
mov eax, DWORD PTR gs:20 ;
mov DWORD PTR [ebp12], eax
xor eax, eax
call _snprintf
mov DWORD PTR [esp], ebx
call puts
mov eax, DWORD PTR [ebp12]
xor eax, DWORD PTR gs:20 ;
6 , : wikipedia.org/wiki/Buffer_overow_protection
7 canary
8 miningwiki.ru/wiki/__

282
18. 18.
jne .L5
mov ebx, DWORD PTR [ebp4]
leave
ret
.L5:
call __stack_chk_fail

gs:20. , , ,
gs:20. , __stack_chk_fail
- (Ubuntu 13.04 x86):
*** buffer overflow detected ***: ./2_1 terminated
======= Backtrace: =========
/lib/i386linuxgnu/libc.so.6(__fortify_fail+0x63)[0xb7699bc3]
/lib/i386linuxgnu/libc.so.6(+0x10593a)[0xb769893a]
/lib/i386linuxgnu/libc.so.6(+0x105008)[0xb7698008]
/lib/i386linuxgnu/libc.so.6(_IO_default_xsputn+0x8c)[0xb7606e5c]
/lib/i386linuxgnu/libc.so.6(_IO_vfprintf+0x165)[0xb75d7a45]
/lib/i386linuxgnu/libc.so.6(__vsprintf_chk+0xc9)[0xb76980d9]
/lib/i386linuxgnu/libc.so.6(__sprintf_chk+0x2f)[0xb7697fef]
./2_1[0x8048404]
/lib/i386linuxgnu/libc.so.6(__libc_start_main+0xf5)[0xb75ac935]
======= Memory map: ========
0804800008049000 rxp 00000000 08:01 2097586 /home/dennis/2_1
080490000804a000 rp 00000000 08:01 2097586 /home/dennis/2_1
0804a0000804b000 rwp 00001000 08:01 2097586 /home/dennis/2_1
094d1000094f2000 rwp 00000000 00:00 0 [heap]
b7560000b757b000 rxp 00000000 08:01 1048602 /lib/i386linuxgnu/libgcc_s.so.1
b757b000b757c000 rp 0001a000 08:01 1048602 /lib/i386linuxgnu/libgcc_s.so.1
b757c000b757d000 rwp 0001b000 08:01 1048602 /lib/i386linuxgnu/libgcc_s.so.1
b7592000b7593000 rwp 00000000 00:00 0
b7593000b7740000 rxp 00000000 08:01 1050781 /lib/i386linuxgnu/libc2.17.so
b7740000b7742000 rp 001ad000 08:01 1050781 /lib/i386linuxgnu/libc2.17.so
b7742000b7743000 rwp 001af000 08:01 1050781 /lib/i386linuxgnu/libc2.17.so
b7743000b7746000 rwp 00000000 00:00 0
b775a000b775d000 rwp 00000000 00:00 0
b775d000b775e000 rxp 00000000 00:00 0 [vdso]
b775e000b777e000 rxp 00000000 08:01 1050794 /lib/i386linuxgnu/ld2.17.so
b777e000b777f000 rp 0001f000 08:01 1050794 /lib/i386linuxgnu/ld2.17.so
b777f000b7780000 rwp 00020000 08:01 1050794 /lib/i386linuxgnu/ld2.17.so
bff35000bff56000 rwp 00000000 00:00 0 [stack]
Aborted (core dumped)

gs . MS-DOS DOS-.
. , Linux gs TLS (65 (. 697))
, . , win32 -
fs, TIB9 10 .
Linux ( , 3.11): arch/x86/include/asm/st
.

18.3.1. Xcode 4.6.3 (LLVM) ( Thumb-2)

(18.1 (. 267)), , LLVM :


_main

var_64 = 0x64
var_60 = 0x60
var_5C = 0x5C
var_58 = 0x58
var_54 = 0x54
var_50 = 0x50
var_4C = 0x4C
var_48 = 0x48
var_44 = 0x44
9 Thread Information Block
10 wikipedia.org/wiki/Win32_Thread_Information_Block

283
18. 18.
var_40 = 0x40
var_3C = 0x3C
var_38 = 0x38
var_34 = 0x34
var_30 = 0x30
var_2C = 0x2C
var_28 = 0x28
var_24 = 0x24
var_20 = 0x20
var_1C = 0x1C
var_18 = 0x18
canary = 0x14
var_10 = 0x10

PUSH {R4R7,LR}
ADD R7, SP, #0xC
STR.W R8, [SP,#0xC+var_10]!
SUB SP, SP, #0x54
MOVW R0, #aObjc_methtype ; "objc_methtype"
MOVS R2, #0
MOVT.W R0, #0
MOVS R5, #0
ADD R0, PC
LDR.W R8, [R0]
LDR.W R0, [R8]
STR R0, [SP,#0x64+canary]
MOVS R0, #2
STR R2, [SP,#0x64+var_64]
STR R0, [SP,#0x64+var_60]
MOVS R0, #4
STR R0, [SP,#0x64+var_5C]
MOVS R0, #6
STR R0, [SP,#0x64+var_58]
MOVS R0, #8
STR R0, [SP,#0x64+var_54]
MOVS R0, #0xA
STR R0, [SP,#0x64+var_50]
MOVS R0, #0xC
STR R0, [SP,#0x64+var_4C]
MOVS R0, #0xE
STR R0, [SP,#0x64+var_48]
MOVS R0, #0x10
STR R0, [SP,#0x64+var_44]
MOVS R0, #0x12
STR R0, [SP,#0x64+var_40]
MOVS R0, #0x14
STR R0, [SP,#0x64+var_3C]
MOVS R0, #0x16
STR R0, [SP,#0x64+var_38]
MOVS R0, #0x18
STR R0, [SP,#0x64+var_34]
MOVS R0, #0x1A
STR R0, [SP,#0x64+var_30]
MOVS R0, #0x1C
STR R0, [SP,#0x64+var_2C]
MOVS R0, #0x1E
STR R0, [SP,#0x64+var_28]
MOVS R0, #0x20
STR R0, [SP,#0x64+var_24]
MOVS R0, #0x22
STR R0, [SP,#0x64+var_20]
MOVS R0, #0x24
STR R0, [SP,#0x64+var_1C]
MOVS R0, #0x26
STR R0, [SP,#0x64+var_18]
MOV R4, 0xFDA ; "a[%d]=%d\n"
MOV R0, SP
ADDS R6, R0, #4
ADD R4, PC
B loc_2F1C

284
18. 18.

loc_2F14
ADDS R0, R5, #1
LDR.W R2, [R6,R5,LSL#2]
MOV R5, R0

loc_2F1C
MOV R0, R4
MOV R1, R5
BLX _printf
CMP R5, #0x13
BNE loc_2F14
LDR.W R0, [R8]
LDR R1, [SP,#0x64+canary]
CMP R0, R1
ITTTT EQ ; ?
MOVEQ R0, #0
ADDEQ SP, SP, #0x54
LDREQ.W R8, [SP+0x64+var_64],#4
POPEQ {R4R7,PC}
BLX ___stack_chk_fail

-, LLVM , ,
LLVM . , ARM
.
, -
R8. , ITTTT EQ. 0 R0,
. ,
___stack_chk_fail, , , .

18.4.
, /++ - :
void f(int size)
{
int a[size];
...
};

, ,
, , .
, , , malloc(),
, .
C99 [ISO07, . 6.7.5/2], alloca() (5.2.4 (. 28)).
, . ++
.

18.5.
.

18.8:
#include <stdio.h>

const char* month1[]=


{
"January",
"February",
"March",

285
18. 18.
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};

// 0..11
const char* get_month1 (int month)
{
return month1[month];
};

18.5.1. x64

18.9: MSVC 2013 x64


_DATA SEGMENT
month1 DQ FLAT:$SG3122
DQ FLAT:$SG3123
DQ FLAT:$SG3124
DQ FLAT:$SG3125
DQ FLAT:$SG3126
DQ FLAT:$SG3127
DQ FLAT:$SG3128
DQ FLAT:$SG3129
DQ FLAT:$SG3130
DQ FLAT:$SG3131
DQ FLAT:$SG3132
DQ FLAT:$SG3133
$SG3122 DB 'January', 00H
$SG3123 DB 'February', 00H
$SG3124 DB 'March', 00H
$SG3125 DB 'April', 00H
$SG3126 DB 'May', 00H
$SG3127 DB 'June', 00H
$SG3128 DB 'July', 00H
$SG3129 DB 'August', 00H
$SG3130 DB 'September', 00H
$SG3156 DB '%s', 0aH, 00H
$SG3131 DB 'October', 00H
$SG3132 DB 'November', 00H
$SG3133 DB 'December', 00H
_DATA ENDS

month$ = 8
get_month1 PROC
movsxd rax, ecx
lea rcx, OFFSET FLAT:month1
mov rax, QWORD PTR [rcx+rax*8]
ret 0
get_month1 ENDP

:
MOVSXD 32- ECX ( :month) RAX -
( month int). ,
64- . ,
64-11 .
RCX.
11 , month ( -

: 52 (. 614)) . , int
. .

286
18. 18.
, (month) 8 . : 64-
( ) 64 ( 8 ). ,
8 .
month 8 . , MOV.
. 1, , February, ..
GCC 4.9 12 :

18.10: GCC 4.9 x64


movsx rdi, edi
mov rax, QWORD PTR month1[0+rdi*8]
ret

32-bit MSVC

32- MSVC:

18.11: MSVC 2013 x86


_month$ = 8
_get_month1 PROC
mov eax, DWORD PTR _month$[esp4]
mov eax, DWORD PTR _month1[eax*4]
ret 0
_get_month1 ENDP

64- , .
4, 32 4 .

18.5.2. 32- ARM

ARM ARM

18.12: Keil 6/2013 ( ARM)


get_month1 PROC
LDR r1,|L0.100|
LDR r0,[r1,r0,LSL #2]
BX lr
ENDP

|L0.100|
DCD ||.data||

DCB "January",0
DCB "February",0
DCB "March",0
DCB "April",0
DCB "May",0
DCB "June",0
DCB "July",0
DCB "August",0
DCB "September",0
DCB "October",0
DCB "November",0
DCB "December",0

AREA ||.data||, DATA, ALIGN=2


month1
DCD ||.conststring||
DCD ||.conststring||+0x8
DCD ||.conststring||+0x11
DCD ||.conststring||+0x17
DCD ||.conststring||+0x1d
DCD ||.conststring||+0x21
12 0+, GCC , . displacement .

287
18. 18.
DCD ||.conststring||+0x26
DCD ||.conststring||+0x2b
DCD ||.conststring||+0x32
DCD ||.conststring||+0x3c
DCD ||.conststring||+0x44
DCD ||.conststring||+0x4d

R1. , LDR.
month 2 ( 4), R1 (
) . 32- R0
.

ARM Thumb

, , , LDR, LSL:
get_month1 PROC
LSLS r0,r0,#2
LDR r1,|L0.64|
LDR r0,[r1,r0]
BX lr
ENDP

18.5.3. ARM64

18.13: GCC 4.9 ARM64


get_month1:
adrp x1, .LANCHOR0
add x1, x1, :lo12:.LANCHOR0
ldr x0, [x1,w0,sxtw 3]
ret

.LANCHOR0 = . + 0
.type month1, %object
.size month1, 96
month1:
.xword .LC2
.xword .LC3
.xword .LC4
.xword .LC5
.xword .LC6
.xword .LC7
.xword .LC8
.xword .LC9
.xword .LC10
.xword .LC11
.xword .LC12
.xword .LC13
.LC2:
.string "January"
.LC3:
.string "February"
.LC4:
.string "March"
.LC5:
.string "April"
.LC6:
.string "May"
.LC7:
.string "June"
.LC8:
.string "July"
.LC9:
.string "August"
.LC10:
.string "September"

288
18. 18.
.LC11:
.string "October"
.LC12:
.string "November"
.LC13:
.string "December"

X1 ADRP/ ADD. -
LDR, W0 (, month), 3
( 8), , ( , sxtw)
X0. 64- X0.

18.5.4. MIPS

18.14: GCC 4.4.5 (IDA)


get_month1:
; $v0:
la $v0, month1
; 4:
sll $a0, 2
; :
addu $a0, $v0
; $v0:
lw $v0, 0($a0)
;
jr $ra
or $at, $zero ; branch delay slot, NOP

.data # .data.rel.local
.globl month1
month1: .word aJanuary # "January"
.word aFebruary # "February"
.word aMarch # "March"
.word aApril # "April"
.word aMay # "May"
.word aJune # "June"
.word aJuly # "July"
.word aAugust # "August"
.word aSeptember # "September"
.word aOctober # "October"
.word aNovember # "November"
.word aDecember # "December"

.data # .rodata.str1.4
aJanuary: .ascii "January"<0>
aFebruary: .ascii "February"<0>
aMarch: .ascii "March"<0>
aApril: .ascii "April"<0>
aMay: .ascii "May"<0>
aJune: .ascii "June"<0>
aJuly: .ascii "July"<0>
aAugust: .ascii "August"<0>
aSeptember: .ascii "September"<0>
aOctober: .ascii "October"<0>
aNovember: .ascii "November"<0>
aDecember: .ascii "December"<0>

18.5.5.

0..11, , 12?
. - , , . ,
- , , .
MSVC win64 IDA ,
:

289
18. 18.
18.15: IDA
off_140011000 dq offset aJanuary_1 ; DATA XREF: .text:0000000140001003
; "January"
dq offset aFebruary_1 ; "February"
dq offset aMarch_1 ; "March"
dq offset aApril_1 ; "April"
dq offset aMay_1 ; "May"
dq offset aJune_1 ; "June"
dq offset aJuly_1 ; "July"
dq offset aAugust_1 ; "August"
dq offset aSeptember_1 ; "September"
dq offset aOctober_1 ; "October"
dq offset aNovember_1 ; "November"
dq offset aDecember_1 ; "December"
aJanuary_1 db 'January',0 ; DATA XREF: sub_140001020+4
; .data:off_140011000
aFebruary_1 db 'February',0 ; DATA XREF: .data:0000000140011008
align 4
aMarch_1 db 'March',0 ; DATA XREF: .data:0000000140011010
align 4
aApril_1 db 'April',0 ; DATA XREF: .data:0000000140011018

. - , (
) . ,
, , .
12 ? 13- . , CPU
64- :

18.16: IDA
off_140011000 dq offset qword_140011060
; DATA XREF: .text:0000000140001003
dq offset aFebruary_1 ; "February"
dq offset aMarch_1 ; "March"
dq offset aApril_1 ; "April"
dq offset aMay_1 ; "May"
dq offset aJune_1 ; "June"
dq offset aJuly_1 ; "July"
dq offset aAugust_1 ; "August"
dq offset aSeptember_1 ; "September"
dq offset aOctober_1 ; "October"
dq offset aNovember_1 ; "November"
dq offset aDecember_1 ; "December"
qword_140011060 dq 797261756E614Ah ; DATA XREF: sub_140001020+4
; .data:off_140011000
aFebruary_1 db 'February',0 ; DATA XREF: .data:0000000140011008
align 4
aMarch_1 db 'March',0 ; DATA XREF: .data:0000000140011010

0x797261756E614A. , - (, ) -
, -. ,
.

- ,

, ,
11. fail early and fail loudly fail-fast,
. /++ assert().
, :

18.17: assert()
const char* get_month1_checked (int month)

290
18. 18.
{
assert (month<12);
return month1[month];
};


false.

18.18: MSVC 2013 x64


$SG3143 DB 'm', 00H, 'o', 00H, 'n', 00H, 't', 00H, 'h', 00H, '.', 00H
DB 'c', 00H, 00H, 00H
$SG3144 DB 'm', 00H, 'o', 00H, 'n', 00H, 't', 00H, 'h', 00H, '<', 00H
DB '1', 00H, '2', 00H, 00H, 00H

month$ = 48
get_month1_checked PROC
$LN5:
push rbx
sub rsp, 32
movsxd rbx, ecx
cmp ebx, 12
jl SHORT $LN3@get_month1
lea rdx, OFFSET FLAT:$SG3143
lea rcx, OFFSET FLAT:$SG3144
mov r8d, 29
call _wassert
$LN3@get_month1:
lea rcx, OFFSET FLAT:month1
mov rax, QWORD PTR [rcx+rbx*8]
add rsp, 32
pop rbx
ret 0
get_month1_checked ENDP

, assert() , .
, . ,
UTF-16. ( 29).
, , . GCC:

18.19: GCC 4.9 x64


.LC1:
.string "month.c"
.LC2:
.string "month<12"

get_month1_checked:
cmp edi, 11
jg .L6
movsx rdi, edi
mov rax, QWORD PTR month1[0+rdi*8]
ret
.L6:
push rax
mov ecx, OFFSET FLAT:__PRETTY_FUNCTION__.2423
mov edx, 29
mov esi, OFFSET FLAT:.LC1
mov edi, OFFSET FLAT:.LC2
call __assert_fail

__PRETTY_FUNCTION__.2423:
.string "get_month1_checked"

GCC , .
. , -
assert() . , , MSVC
, .

291
18. 18.
Microsoft Windows NT checked free13 .
( checked), ( free, .. ).

18.6.
. ,
. .
, 3x4 12 :


0 [0][0]
1 [0][1]
2 [0][2]
3 [0][3]
4 [1][0]
5 [1][1]
6 [1][2]
7 [1][3]
8 [2][0]
9 [2][1]
10 [2][2]
11 [2][3]

18.1:

3*4:

0 1 2 3
4 5 6 7
8 9 10 11

18.2:

, () 4 ( ),
(). row-major order,
/++ Python. row-major order - :
, , .
column-major order ( )
FORTRAN, MATLAB R. column-major order - :
, , .
? -, ,
. ,
row-major order , .

18.6.1.

char. , .

0..3:

18.20:
#include <stdio.h>

char a[3][4];

13 msdn.microsoft.com/en-us/library/windows/hardware/ff543450(v=vs.85).aspx

292
18. 18.
int main()
{
int x, y;

//
for (x=0; x<3; x++)
for (y=0; y<4; y++)
a[x][y]=0;

// 0..3:
for (y=0; y<4; y++)
a[1][y]=y;
};

. , 0, 1, 2 3:

. 18.7: OllyDbg:

0..2:

18.21:
#include <stdio.h>

char a[3][4];

int main()
{
int x, y;

//
for (x=0; x<3; x++)
for (y=0; y<4; y++)
a[x][y]=0;

// 0..2:
for (x=0; x<3; x++)
a[x][2]=x;
};

. , , , 0, 1 2.

. 18.8: OllyDbg:

18.6.2.

, ,
:

293
18. 18.

#include <stdio.h>

char a[3][4];

char get_by_coordinates1 (char array[3][4], int a, int b)


{
return array[a][b];
};

char get_by_coordinates2 (char *array, int a, int b)


{
//
// 4
return array[a*4+b];
};

char get_by_coordinates3 (char *array, int a, int b)


{
// ,
// ,
// 4
return *(array+a*4+b);
};

int main()
{
a[2][3]=123;
printf ("%d\n", get_by_coordinates1(a, 2, 3));
printf ("%d\n", get_by_coordinates2(a, 2, 3));
printf ("%d\n", get_by_coordinates3(a, 2, 3));
};

: .
MSVC 2013 !

18.22: MSVC 2013 x64


array$ = 8
a$ = 16
b$ = 24
get_by_coordinates3 PROC
; RCX=
; RDX=a
; R8=b
movsxd rax, r8d
; EAX=b
movsxd r9, edx
; R9=a
add rax, rcx
; RAX=b+
movzx eax, BYTE PTR [rax+r9*4]
; AL= RAX+R9*4=b+ +a*4= +a*4+b
ret 0
get_by_coordinates3 ENDP

array$ = 8
a$ = 16
b$ = 24
get_by_coordinates2 PROC
movsxd rax, r8d
movsxd r9, edx
add rax, rcx
movzx eax, BYTE PTR [rax+r9*4]
ret 0
get_by_coordinates2 ENDP

array$ = 8
a$ = 16
b$ = 24

294
18. 18.
get_by_coordinates1 PROC
movsxd rax, r8d
movsxd r9, edx
add rax, rcx
movzx eax, BYTE PTR [rax+r9*4]
ret 0
get_by_coordinates1 ENDP

GCC :

18.23: GCC 4.9 x64


; RDI=
; RSI=a
; RDX=b

get_by_coordinates1:
; 32- "a" "b" 64-
movsx rsi, esi
movsx rdx, edx
lea rax, [rdi+rsi*4]
; RAX=RDI+RSI*4= +a*4
movzx eax, BYTE PTR [rax+rdx]
; AL= RAX+RDX= +a*4+b
ret

get_by_coordinates2:
lea eax, [rdx+rsi*4]
; RAX=RDX+RSI*4=b+a*4
cdqe
movzx eax, BYTE PTR [rdi+rax]
; AL= RDI+RAX= +b+a*4
ret

get_by_coordinates3:
sal esi, 2
; ESI=a<<2=a*4
; 32- "a*4" "b" 64-
movsx rdx, edx
movsx rsi, esi
add rdi, rsi
; RDI=RDI+RSI= +a*4
movzx eax, BYTE PTR [rdi+rdx]
; AL= RDI+RDX= +a*4+b
ret

18.6.3.

. int: 4
.
:

18.24:
#include <stdio.h>

int a[10][20][30];

void insert(int x, int y, int z, int value)


{
a[x][y][z]=value;
};

x86

(MSVC 2010):

295
18. 18.
18.25: MSVC 2010
_DATA SEGMENT
COMM _a:DWORD:01770H
_DATA ENDS
PUBLIC _insert
_TEXT SEGMENT
_x$ = 8 ; size = 4
_y$ = 12 ; size = 4
_z$ = 16 ; size = 4
_value$ = 20 ; size = 4
_insert PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _x$[ebp]
imul eax, 2400 ; eax=600*4*x
mov ecx, DWORD PTR _y$[ebp]
imul ecx, 120 ; ecx=30*4*y
lea edx, DWORD PTR _a[eax+ecx] ; edx=a + 600*4*x + 30*4*y
mov eax, DWORD PTR _z$[ebp]
mov ecx, DWORD PTR _value$[ebp]
mov DWORD PTR [edx+eax*4], ecx ; *(edx+z*4)=
pop ebp
ret 0
_insert ENDP
_TEXT ENDS

, . insert() -
address = 6004x+304y+4z, .
, int 32- (4 ), 4.

18.26: GCC 4.4.1


public insert
insert proc near

x = dword ptr 8
y = dword ptr 0Ch
z = dword ptr 10h
value = dword ptr 14h

push ebp
mov ebp, esp
push ebx
mov ebx, [ebp+x]
mov eax, [ebp+y]
mov ecx, [ebp+z]
lea edx, [eax+eax] ; edx=y*2
mov eax, edx ; eax=y*2
shl eax, 4 ; eax=(y*2)<<4 = y*2*16 = y*32
sub eax, edx ; eax=y*32 y*2=y*30
imul edx, ebx, 600 ; edx=x*600
add eax, edx ; eax=eax+edx=y*30 + x*600
lea edx, [eax+ecx] ; edx=y*30 + x*600 + z
mov eax, [ebp+value]
mov dword ptr ds:a[edx*4], eax ; *(a+edx*4)=
pop ebx
pop ebp
retn
insert endp

GCC . (30y), GCC ,


. : (y+y) 4(y+y) = (2y) 42y = 216y2y = 32y2y = 30y.
, 30y , .
.

ARM + Xcode 4.6.3 (LLVM) ( Thumb)

296
18. 18.
18.27: Xcode 4.6.3 (LLVM) ( Thumb)
_insert

value = 0x10
z = 0xC
y = 8
x = 4

; 4 int
SUB SP, SP, #0x10
MOV R9, 0xFC2 ; a
ADD R9, PC
LDR.W R9, [R9]
STR R0, [SP,#0x10+x]
STR R1, [SP,#0x10+y]
STR R2, [SP,#0x10+z]
STR R3, [SP,#0x10+value]
LDR R0, [SP,#0x10+value]
LDR R1, [SP,#0x10+z]
LDR R2, [SP,#0x10+y]
LDR R3, [SP,#0x10+x]
MOV R12, 2400
MUL.W R3, R3, R12
ADD R3, R9
MOV R9, 120
MUL.W R2, R2, R9
ADD R2, R3
LSLS R1, R1, #2 ; R1=R1<<2
ADD R1, R2
STR R0, [R1] ; R1
; , 4
ADD SP, SP, #0x10
BX LR

LLVM , .
.

ARM + Xcode 4.6.3 (LLVM) ( Thumb)

18.28: Xcode 4.6.3 (LLVM) ( Thumb)


_insert
MOVW R9, #0x10FC
MOV.W R12, #2400
MOVT.W R9, #0
RSB.W R1, R1, R1,LSL#4 ; R1 y. R1=y<<4 y = y*16 y = y*15
ADD R9, PC ; R9 =
LDR.W R9, [R9]
MLA.W R0, R0, R12, R9 ; R0 x, R12 2400, R9 a. R0=x*2400 + a
ADD.W R0, R0, R1,LSL#3 ; R0 = R0+R1<<3 = R0+R1*8 = x*2400 + a + y*15*8 =
; a + y*30*4 + x*600*4
STR.W R3, [R0,R2,LSL#2] ; R2 z, R3 . =R0+z*4 =
; a + y*30*4 + x*600*4 + z*4
BX LR

, .
RSB (Reverse Subtract). , SUB, -
. ? SUB RSB ,
, : (LSL#4). . -
, , .
, RSB.
LDR.W R9, [R9] LEA (A.6.2 (. 965)) x86, , .
, .

297
18. 18.
MIPS

, GCC a 64KiB-, -
Global Pointer.

18.29: GCC 4.4.5 (IDA)


insert:
; $a0=x
; $a1=y
; $a2=z
; $a3=
sll $v0, $a0, 5
; $v0 = $a0<<5 = x*32
sll $a0, 3
; $a0 = $a0<<3 = x*8
addu $a0, $v0
; $a0 = $a0+$v0 = x*8+x*32 = x*40
sll $v1, $a1, 5
; $v1 = $a1<<5 = y*32
sll $v0, $a0, 4
; $v0 = $a0<<4 = x*40*16 = x*640
sll $a1, 1
; $a1 = $a1<<1 = y*2
subu $a1, $v1, $a1
; $a1 = $v1$a1 = y*32y*2 = y*30
subu $a0, $v0, $a0
; $a0 = $v0$a0 = x*640x*40 = x*600
la $gp, __gnu_local_gp
addu $a0, $a1, $a0
; $a0 = $a1+$a0 = y*30+x*600
addu $a0, $a2
; $a0 = $a0+$a2 = y*30+x*600+z
; :
lw $v0, (a & 0xFFFF)($gp)
; 4 :
sll $a0, 2
; :
addu $a0, $v0, $a0
; :
jr $ra
sw $a3, 0($a0)

.comm a:0x1770

18.6.4.

, .
: 83.2 (. 852).

18.7.
, : .18.8. ,
, .
? , :
#include <stdio.h>
#include <assert.h>

const char month2[12][10]=


{
{ 'J','a','n','u','a','r','y', 0, 0, 0 },
{ 'F','e','b','r','u','a','r','y', 0, 0 },
{ 'M','a','r','c','h', 0, 0, 0, 0, 0 },
{ 'A','p','r','i','l', 0, 0, 0, 0, 0 },
{ 'M','a','y', 0, 0, 0, 0, 0, 0, 0 },

298
18. 18.
{ 'J','u','n','e', 0, 0, 0, 0, 0, 0 },
{ 'J','u','l','y', 0, 0, 0, 0, 0, 0 },
{ 'A','u','g','u','s','t', 0, 0, 0, 0 },
{ 'S','e','p','t','e','m','b','e','r', 0 },
{ 'O','c','t','o','b','e','r', 0, 0, 0 },
{ 'N','o','v','e','m','b','e','r', 0, 0 },
{ 'D','e','c','e','m','b','e','r', 0, 0 }
};

// 0..11
const char* get_month2 (int month)
{
return &month2[month][0];
};

18.30: MSVC 2013 x64


month2 DB 04aH
DB 061H
DB 06eH
DB 075H
DB 061H
DB 072H
DB 079H
DB 00H
DB 00H
DB 00H
...

get_month2 PROC
; 64-,
movsxd rax, ecx
lea rcx, QWORD PTR [rax+rax*4]
; RCX=+*4=*5
lea rax, OFFSET FLAT:month2
; RAX=
lea rax, QWORD PTR [rax+rcx*2]
; RAX= + RCX*2= + *5*2= + *10
ret 0
get_month2 ENDP

. ,
: pointer_to_the_table + month 10. LEA,
MUL MOV.
10 . , September (9 ) ,
10 . ,
(10 ). , , ,
.
GCC 4.9 :

18.31: GCC 4.9 x64


movsx rdi, edi
lea rax, [rdi+rdi*4]
lea rax, month2[rax+rax]
ret

LEA 10.
-.

18.32: GCC 4.9 x64


get_month2:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp4], edi
mov eax, DWORD PTR [rbp4]

299
18. 18.
movsx rdx, eax
; RDX = ,
mov rax, rdx
; RAX =
sal rax, 2
; RAX = <<2 = *4
add rax, rdx
; RAX = RAX+RDX = *4+ = *5
add rax, rax
; RAX = RAX*2 = *5*2 = *10
add rax, OFFSET FLAT:month2
; RAX = *10 +
pop rbp
ret

MSVC IMUL:

18.33: MSVC 2013 x64


month$ = 8
get_month2 PROC
mov DWORD PTR [rsp+8], ecx
movsxd rax, DWORD PTR month$[rsp]
; RAX = 64- ,
imul rax, rax, 10
; RAX = RAX*10
lea rcx, OFFSET FLAT:month2
; RCX =
add rcx, rax
; RCX = RCX+RAX = +month*10
mov rax, rcx
; RAX = +*10
mov ecx, 1
; RCX = 1
imul rcx, rcx, 0
; RCX = 1*0 = 0
add rax, rcx
; RAX = +*10 + 0 = +*10
ret 0
get_month2 ENDP

: ?
, . ,
. , ,
.

18.7.1. 32-bit ARM

Keil Thumb MULS:

18.34: Keil 6/2013 ( Thumb)


; R0 =
MOVS r1,#0xa
; R1 = 10
MULS r0,r1,r0
; R0 = R1*R0 = 10*
LDR r1,|L0.68|
; R1 =
ADDS r0,r0,r1
; R0 = R0+R1 = 10* +
BX lr

Keil ARM :

18.35: Keil 6/2013 ( ARM)


; R0 =
LDR r1,|L0.104|
; R1 =

300
18. 18.
ADD r0,r0,r0,LSL #2
; R0 = R0+R0<<2 = R0+R0*4 = *5
ADD r0,r1,r0,LSL #1
; R0 = R1+R0<<2 = + *5*2 = + *10
BX lr

18.7.2. ARM64

18.36: GCC 4.9 ARM64


; W0 =
sxtw x0, w0
; X0 =
adrp x1, .LANCHOR1
add x1, x1, :lo12:.LANCHOR1
; X1 =
add x0, x0, x0, lsl 2
; X0 = X0+X0<<2 = X0+X0*4 = X0*5
add x0, x1, x0, lsl 1
; X0 = X1+X0<<1 = X1+X0*2 = + X0*10
ret

SXTW 32- 64-


X0. ADRP/ ADD . ADD LSL,
.

18.7.3. MIPS

18.37: GCC 4.4.5 (IDA)


.globl get_month2
get_month2:
; $a0=
sll $v0, $a0, 3
; $v0 = $a0<<3 = *8
sll $a0, 1
; $a0 = $a0<<1 = *2
addu $a0, $v0
; $a0 = *2+*8 = *10
; :
la $v0, month2
; :
jr $ra
addu $v0, $a0

month2: .ascii "January"<0>


.byte 0, 0
aFebruary: .ascii "February"<0>
.byte 0
aMarch: .ascii "March"<0>
.byte 0, 0, 0, 0
aApril: .ascii "April"<0>
.byte 0, 0, 0, 0
aMay: .ascii "May"<0>
.byte 0, 0, 0, 0, 0, 0
aJune: .ascii "June"<0>
.byte 0, 0, 0, 0, 0
aJuly: .ascii "July"<0>
.byte 0, 0, 0, 0, 0
aAugust: .ascii "August"<0>
.byte 0, 0, 0
aSeptember: .ascii "September"<0>
aOctober: .ascii "October"<0>
.byte 0, 0
aNovember: .ascii "November"<0>
.byte 0

301
18. 18.
aDecember: .ascii "December"<0>
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0

18.7.4.

. Oracle RDBMS, .
, . , ,
.

18.8.
, .
, . .

18.9.

18.9.1. #1

18.38: MSVC 2010 + /O1


_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_c$ = 16 ; size = 4
?s@@YAXPAN00@Z PROC ; s, COMDAT
mov eax, DWORD PTR _b$[esp4]
mov ecx, DWORD PTR _a$[esp4]
mov edx, DWORD PTR _c$[esp4]
push esi
push edi
sub ecx, eax
sub edx, eax
mov edi, 200 ; 000000c8H
$LL6@s:
push 100 ; 00000064H
pop esi
$LL3@s:
fld QWORD PTR [ecx+eax]
fadd QWORD PTR [eax]
fstp QWORD PTR [edx+eax]
add eax, 8
dec esi
jne SHORT $LL3@s
dec edi
jne SHORT $LL6@s
pop edi
pop esi
ret 0
?s@@YAXPAN00@Z ENDP ; s

(/O1: ).

18.39: Keil 6/2013 ( ARM)


PUSH {r4r12,lr}
MOV r9,r2
MOV r10,r1
MOV r11,r0
MOV r5,#0
|L0.20|
ADD r0,r5,r5,LSL #3
ADD r0,r0,r5,LSL #4
MOV r4,#0

302
18. 18.
ADD r8,r10,r0,LSL #5
ADD r7,r11,r0,LSL #5
ADD r6,r9,r0,LSL #5
|L0.44|
ADD r0,r8,r4,LSL #3
LDM r0,{r2,r3}
ADD r1,r7,r4,LSL #3
LDM r1,{r0,r1}
BL __aeabi_dadd
ADD r2,r6,r4,LSL #3
ADD r4,r4,#1
STM r2,{r0,r1}
CMP r4,#0x64
BLT |L0.44|
ADD r5,r5,#1
CMP r5,#0xc8
BLT |L0.20|
POP {r4r12,pc}

18.40: Keil 6/2013 ( Thumb)


PUSH {r0r2,r4r7,lr}
MOVS r4,#0
SUB sp,sp,#8
|L0.6|
MOVS r1,#0x19
MOVS r0,r4
LSLS r1,r1,#5
MULS r0,r1,r0
LDR r2,[sp,#8]
LDR r1,[sp,#0xc]
ADDS r2,r0,r2
STR r2,[sp,#0]
LDR r2,[sp,#0x10]
MOVS r5,#0
ADDS r7,r0,r2
ADDS r0,r0,r1
STR r0,[sp,#4]
|L0.32|
LSLS r6,r5,#3
ADDS r0,r0,r6
LDM r0!,{r2,r3}
LDR r0,[sp,#0]
ADDS r1,r0,r6
LDM r1,{r0,r1}
BL __aeabi_dadd
ADDS r2,r7,r6
ADDS r5,r5,#1
STM r2!,{r0,r1}
CMP r5,#0x64
BGE |L0.62|
LDR r0,[sp,#4]
B |L0.32|
|L0.62|
ADDS r4,r4,#1
CMP r4,#0xc8
BLT |L0.6|
ADD sp,sp,#0x14
POP {r4r7,pc}

18.41: GCC 4.9 (ARM64)


s:
sub sp, sp, #48
str x0, [sp,24]
str x1, [sp,16]
str x2, [sp,8]
str wzr, [sp,44]
b .L2
.L5:

303
18. 18.
str wzr, [sp,40]
b .L3
.L4:
ldr w1, [sp,44]
mov w0, 100
mul w0, w1, w0
sxtw x1, w0
ldrsw x0, [sp,40]
add x0, x1, x0
lsl x0, x0, 3
ldr x1, [sp,8]
add x0, x1, x0
ldr w2, [sp,44]
mov w1, 100
mul w1, w2, w1
sxtw x2, w1
ldrsw x1, [sp,40]
add x1, x2, x1
lsl x1, x1, 3
ldr x2, [sp,24]
add x1, x2, x1
ldr x2, [x1]
ldr w3, [sp,44]
mov w1, 100
mul w1, w3, w1
sxtw x3, w1
ldrsw x1, [sp,40]
add x1, x3, x1
lsl x1, x1, 3
ldr x3, [sp,16]
add x1, x3, x1
ldr x1, [x1]
fmov d0, x2
fmov d1, x1
fadd d0, d0, d1
fmov x1, d0
str x1, [x0]
ldr w0, [sp,40]
add w0, w0, 1
str w0, [sp,40]
.L3:
ldr w0, [sp,40]
cmp w0, 99
ble .L4
ldr w0, [sp,44]
add w0, w0, 1
str w0, [sp,44]
.L2:
ldr w0, [sp,44]
cmp w0, 199
ble .L5
add sp, sp, 48
ret

18.42: GCC 4.4.5 (MIPS) (IDA)


sub_0:
li $t3, 0x27100
move $t2, $zero
li $t1, 0x64 # 'd'

loc_10: # CODE XREF: sub_0+54


addu $t0, $a1, $t2
addu $a3, $a2, $t2
move $v1, $a0
move $v0, $zero

loc_20: # CODE XREF: sub_0+48


lwc1 $f2, 4($v1)
lwc1 $f0, 4($t0)

304
18. 18.
lwc1 $f3, 0($v1)
lwc1 $f1, 0($t0)
addiu $v0, 1
add.d $f0, $f2, $f0
addiu $v1, 8
swc1 $f0, 4($a3)
swc1 $f1, 0($a3)
addiu $t0, 8
bne $v0, $t1, loc_20
addiu $a3, 8
addiu $t2, 0x320
bne $t2, $t3, loc_10
addiu $a0, 0x320
jr $ra
or $at, $zero

G.1.12 (. 988).

18.9.2. #2

18.43: MSVC 2010 + /O1


tv315 = 8 ; size = 4
tv291 = 4 ; size = 4
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_c$ = 16 ; size = 4
?m@@YAXPAN00@Z PROC ; m, COMDAT
push ebp
mov ebp, esp
push ecx
push ecx
mov edx, DWORD PTR _a$[ebp]
push ebx
mov ebx, DWORD PTR _c$[ebp]
push esi
mov esi, DWORD PTR _b$[ebp]
sub edx, esi
push edi
sub esi, ebx
mov DWORD PTR tv315[ebp], 100 ; 00000064H
$LL9@m:
mov eax, ebx
mov DWORD PTR tv291[ebp], 300 ; 0000012cH
$LL6@m:
fldz
lea ecx, DWORD PTR [esi+eax]
fstp QWORD PTR [eax]
mov edi, 200 ; 000000c8H
$LL3@m:
dec edi
fld QWORD PTR [ecx+edx]
fmul QWORD PTR [ecx]
fadd QWORD PTR [eax]
fstp QWORD PTR [eax]
jne HORT $LL3@m
add eax, 8
dec DWORD PTR tv291[ebp]
jne SHORT $LL6@m
add ebx, 800 ; 00000320H
dec DWORD PTR tv315[ebp]
jne SHORT $LL9@m
pop edi
pop esi
pop ebx
leave
ret 0

305
18. 18.
?m@@YAXPAN00@Z ENDP ; m

(/O1: ).
18.44: Keil 6/2013 ( ARM)
PUSH {r0r2,r4r11,lr}
SUB sp,sp,#8
MOV r5,#0
|L0.12|
LDR r1,[sp,#0xc]
ADD r0,r5,r5,LSL #3
ADD r0,r0,r5,LSL #4
ADD r1,r1,r0,LSL #5
STR r1,[sp,#0]
LDR r1,[sp,#8]
MOV r4,#0
ADD r11,r1,r0,LSL #5
LDR r1,[sp,#0x10]
ADD r10,r1,r0,LSL #5
|L0.52|
MOV r0,#0
MOV r1,r0
ADD r7,r10,r4,LSL #3
STM r7,{r0,r1}
MOV r6,r0
LDR r0,[sp,#0]
ADD r8,r11,r4,LSL #3
ADD r9,r0,r4,LSL #3
|L0.84|
LDM r9,{r2,r3}
LDM r8,{r0,r1}
BL __aeabi_dmul
LDM r7,{r2,r3}
BL __aeabi_dadd
ADD r6,r6,#1
STM r7,{r0,r1}
CMP r6,#0xc8
BLT |L0.84|
ADD r4,r4,#1
CMP r4,#0x12c
BLT |L0.52|
ADD r5,r5,#1
CMP r5,#0x64
BLT |L0.12|
ADD sp,sp,#0x14
POP {r4r11,pc}

18.45: Keil 6/2013 ( Thumb)


PUSH {r0r2,r4r7,lr}
MOVS r0,#0
SUB sp,sp,#0x10
STR r0,[sp,#0]
|L0.8|
MOVS r1,#0x19
LSLS r1,r1,#5
MULS r0,r1,r0
LDR r2,[sp,#0x10]
LDR r1,[sp,#0x14]
ADDS r2,r0,r2
STR r2,[sp,#4]
LDR r2,[sp,#0x18]
MOVS r5,#0
ADDS r7,r0,r2
ADDS r0,r0,r1
STR r0,[sp,#8]
|L0.32|
LSLS r4,r5,#3
MOVS r0,#0
ADDS r2,r7,r4

306
18. 18.
STR r0,[r2,#0]
MOVS r6,r0
STR r0,[r2,#4]
|L0.44|
LDR r0,[sp,#8]
ADDS r0,r0,r4
LDM r0!,{r2,r3}
LDR r0,[sp,#4]
ADDS r1,r0,r4
LDM r1,{r0,r1}
BL __aeabi_dmul
ADDS r3,r7,r4
LDM r3,{r2,r3}
BL __aeabi_dadd
ADDS r2,r7,r4
ADDS r6,r6,#1
STM r2!,{r0,r1}
CMP r6,#0xc8
BLT |L0.44|
MOVS r0,#0xff
ADDS r5,r5,#1
ADDS r0,r0,#0x2d
CMP r5,r0
BLT |L0.32|
LDR r0,[sp,#0]
ADDS r0,r0,#1
CMP r0,#0x64
STR r0,[sp,#0]
BLT |L0.8|
ADD sp,sp,#0x1c
POP {r4r7,pc}

18.46: GCC 4.9 (ARM64)


m:
sub sp, sp, #48
str x0, [sp,24]
str x1, [sp,16]
str x2, [sp,8]
str wzr, [sp,44]
b .L2
.L7:
str wzr, [sp,40]
b .L3
.L6:
ldr w1, [sp,44]
mov w0, 100
mul w0, w1, w0
sxtw x1, w0
ldrsw x0, [sp,40]
add x0, x1, x0
lsl x0, x0, 3
ldr x1, [sp,8]
add x0, x1, x0
ldr x1, .LC0
str x1, [x0]
str wzr, [sp,36]
b .L4
.L5:
ldr w1, [sp,44]
mov w0, 100
mul w0, w1, w0
sxtw x1, w0
ldrsw x0, [sp,40]
add x0, x1, x0
lsl x0, x0, 3
ldr x1, [sp,8]
add x0, x1, x0
ldr w2, [sp,44]
mov w1, 100

307
18. 18.
mul w1, w2, w1
sxtw x2, w1
ldrsw x1, [sp,40]
add x1, x2, x1
lsl x1, x1, 3
ldr x2, [sp,8]
add x1, x2, x1
ldr x2, [x1]
ldr w3, [sp,44]
mov w1, 100
mul w1, w3, w1
sxtw x3, w1
ldrsw x1, [sp,40]
add x1, x3, x1
lsl x1, x1, 3
ldr x3, [sp,24]
add x1, x3, x1
ldr x3, [x1]
ldr w4, [sp,44]
mov w1, 100
mul w1, w4, w1
sxtw x4, w1
ldrsw x1, [sp,40]
add x1, x4, x1
lsl x1, x1, 3
ldr x4, [sp,16]
add x1, x4, x1
ldr x1, [x1]
fmov d0, x3
fmov d1, x1
fmul d0, d0, d1
fmov x1, d0
fmov d0, x2
fmov d1, x1
fadd d0, d0, d1
fmov x1, d0
str x1, [x0]
ldr w0, [sp,36]
add w0, w0, 1
str w0, [sp,36]
.L4:
ldr w0, [sp,36]
cmp w0, 199
ble .L5
ldr w0, [sp,40]
add w0, w0, 1
str w0, [sp,40]
.L3:
ldr w0, [sp,40]
cmp w0, 299
ble .L6
ldr w0, [sp,44]
add w0, w0, 1
str w0, [sp,44]
.L2:
ldr w0, [sp,44]
cmp w0, 99
ble .L7
add sp, sp, 48
ret

18.47: GCC 4.4.5 (MIPS) (IDA)


m:
li $t5, 0x13880
move $t4, $zero
li $t1, 0xC8
li $t3, 0x12C

loc_14: # CODE XREF: m+7C

308
18. 18.
addu $t0, $a0, $t4
addu $a3, $a1, $t4
move $v1, $a2
move $t2, $zero

loc_24: # CODE XREF: m+70


mtc1 $zero, $f0
move $v0, $zero
mtc1 $zero, $f1
or $at, $zero
swc1 $f0, 4($v1)
swc1 $f1, 0($v1)

loc_3C: # CODE XREF: m+5C


lwc1 $f4, 4($t0)
lwc1 $f2, 4($a3)
lwc1 $f5, 0($t0)
lwc1 $f3, 0($a3)
addiu $v0, 1
mul.d $f2, $f4, $f2
add.d $f0, $f2
swc1 $f0, 4($v1)
bne $v0, $t1, loc_3C
swc1 $f1, 0($v1)
addiu $t2, 1
addiu $v1, 8
addiu $t0, 8
bne $t2, $t3, loc_24
addiu $a3, 8
addiu $t4, 0x320
bne $t4, $t5, loc_14
addiu $a2, 0x320
jr $ra
or $at, $zero

G.1.12 (. 988).

18.9.3. #3

?
, .

18.48: MSVC 2010


_array$ = 8
_x$ = 12
_y$ = 16
_f PROC
mov eax, DWORD PTR _x$[esp4]
mov edx, DWORD PTR _y$[esp4]
mov ecx, eax
shl ecx, 4
sub ecx, eax
lea eax, DWORD PTR [edx+ecx*8]
mov ecx, DWORD PTR _array$[esp4]
fld QWORD PTR [ecx+eax*8]
ret 0
_f ENDP

18.49: Keil 6/2013 ( ARM)


f PROC
RSB r1,r1,r1,LSL #4
ADD r0,r0,r1,LSL #6
ADD r1,r0,r2,LSL #3
LDM r1,{r0,r1}
BX lr
ENDP

309
18. 18.
18.50: Keil 6/2013 ( Thumb)
f PROC
MOVS r3,#0xf
LSLS r3,r3,#6
MULS r1,r3,r1
ADDS r0,r1,r0
LSLS r1,r2,#3
ADDS r1,r0,r1
LDM r1,{r0,r1}
BX lr
ENDP

18.51: GCC 4.9 (ARM64)


f:
sxtw x1, w1
add x0, x0, x2, sxtw 3
lsl x2, x1, 10
sub x1, x2, x1, lsl 6
ldr d0, [x0,x1]
ret

18.52: GCC 4.4.5 (MIPS) (IDA)


f:
sll $v0, $a1, 10
sll $a1, 6
subu $a1, $v0, $a1
addu $a1, $a0, $a1
sll $a2, 3
addu $a1, $a2
lwc1 $f0, 4($a1)
or $at, $zero
lwc1 $f1, 0($a1)
jr $ra
or $at, $zero

G.1.12 (. 988)

18.9.4. #4

?
, .

18.53: MSVC 2010


_array$ = 8
_x$ = 12
_y$ = 16
_z$ = 20
_f PROC
mov eax, DWORD PTR _x$[esp4]
mov edx, DWORD PTR _y$[esp4]
mov ecx, eax
shl ecx, 4
sub ecx, eax
lea eax, DWORD PTR [edx+ecx*4]
mov ecx, DWORD PTR _array$[esp4]
lea eax, DWORD PTR [eax+eax*4]
shl eax, 4
add eax, DWORD PTR _z$[esp4]
mov eax, DWORD PTR [ecx+eax*4]
ret 0
_f ENDP

18.54: Keil 6/2013 ( ARM)


f PROC

310
18. 18.
RSB r1,r1,r1,LSL #4
ADD r1,r1,r1,LSL #2
ADD r0,r0,r1,LSL #8
ADD r1,r2,r2,LSL #2
ADD r0,r0,r1,LSL #6
LDR r0,[r0,r3,LSL #2]
BX lr
ENDP

18.55: Keil 6/2013 ( Thumb)


f PROC
PUSH {r4,lr}
MOVS r4,#0x4b
LSLS r4,r4,#8
MULS r1,r4,r1
ADDS r0,r1,r0
MOVS r1,#0xff
ADDS r1,r1,#0x41
MULS r2,r1,r2
ADDS r0,r0,r2
LSLS r1,r3,#2
LDR r0,[r0,r1]
POP {r4,pc}
ENDP

18.56: GCC 4.9 (ARM64)


f:
sxtw x2, w2
mov w4, 19200
add x2, x2, x2, lsl 2
smull x1, w1, w4
lsl x2, x2, 4
add x3, x2, x3, sxtw
add x0, x0, x3, lsl 2
ldr w0, [x0,x1]
ret

18.57: GCC 4.4.5 (MIPS) (IDA)


f:
sll $v0, $a1, 10
sll $a1, 8
addu $a1, $v0
sll $v0, $a2, 6
sll $a2, 4
addu $a2, $v0
sll $v0, $a1, 4
subu $a1, $v0, $a1
addu $a2, $a3
addu $a1, $a0, $a1
sll $a2, 2
addu $a1, $a2
lw $v0, 0($a1)
jr $ra
or $at, $zero

G.1.12 (. 988)

18.9.5. #5

18.58: MSVC 2012 /GS-


COMM _tbl:DWORD:064H

tv759 = 4 ; size = 4

311
18. 18.
_main PROC
push ecx
push ebx
push ebp
push esi
xor edx, edx
push edi
xor esi, esi
xor edi, edi
xor ebx, ebx
xor ebp, ebp
mov DWORD PTR tv759[esp+20], edx
mov eax, OFFSET _tbl+4
npad 8 ; align next label
$LL6@main:
lea ecx, DWORD PTR [edx+edx]
mov DWORD PTR [eax+4], ecx
mov ecx, DWORD PTR tv759[esp+20]
add DWORD PTR tv759[esp+20], 3
mov DWORD PTR [eax+8], ecx
lea ecx, DWORD PTR [edx*4]
mov DWORD PTR [eax+12], ecx
lea ecx, DWORD PTR [edx*8]
mov DWORD PTR [eax], edx
mov DWORD PTR [eax+16], ebp
mov DWORD PTR [eax+20], ebx
mov DWORD PTR [eax+24], edi
mov DWORD PTR [eax+32], esi
mov DWORD PTR [eax4], 0
mov DWORD PTR [eax+28], ecx
add eax, 40
inc edx
add ebp, 5
add ebx, 6
add edi, 7
add esi, 9
cmp eax, OFFSET _tbl+404
jl SHORT $LL6@main
pop edi
pop esi
pop ebp
xor eax, eax
pop ebx
pop ecx
ret 0
_main ENDP

18.59: Keil 6/2013 ( ARM)


main PROC
LDR r12,|L0.60|
MOV r1,#0
|L0.8|
ADD r2,r1,r1,LSL #2
MOV r0,#0
ADD r2,r12,r2,LSL #3
|L0.20|
MUL r3,r1,r0
STR r3,[r2,r0,LSL #2]
ADD r0,r0,#1
CMP r0,#0xa
BLT |L0.20|
ADD r1,r1,#1
CMP r1,#0xa
MOVGE r0,#0
BLT |L0.8|
BX lr
ENDP

|L0.60|

312
18. 18.
DCD ||.bss||

AREA ||.bss||, DATA, NOINIT, ALIGN=2

tbl
% 400

18.60: Keil 6/2013 ( Thumb)


main PROC
PUSH {r4,r5,lr}
LDR r4,|L0.40|
MOVS r1,#0
|L0.6|
MOVS r2,#0x28
MULS r2,r1,r2
MOVS r0,#0
ADDS r3,r2,r4
|L0.14|
MOVS r2,r1
MULS r2,r0,r2
LSLS r5,r0,#2
ADDS r0,r0,#1
CMP r0,#0xa
STR r2,[r3,r5]
BLT |L0.14|
ADDS r1,r1,#1
CMP r1,#0xa
BLT |L0.6|
MOVS r0,#0
POP {r4,r5,pc}
ENDP

DCW 0x0000
|L0.40|
DCD ||.bss||

AREA ||.bss||, DATA, NOINIT, ALIGN=2

tbl
% 400

18.61: GCC 4.9 (ARM64)


.comm tbl,400,8
main:
sub sp, sp, #16
str wzr, [sp,12]
b .L2
.L5:
str wzr, [sp,8]
b .L3
.L4:
ldr w1, [sp,12]
ldr w0, [sp,8]
mul w3, w1, w0
adrp x0, tbl
add x2, x0, :lo12:tbl
ldrsw x4, [sp,8]
ldrsw x1, [sp,12]
mov x0, x1
lsl x0, x0, 2
add x0, x0, x1
lsl x0, x0, 1
add x0, x0, x4
str w3, [x2,x0,lsl 2]
ldr w0, [sp,8]
add w0, w0, 1
str w0, [sp,8]
.L3:

313
18. 18.
ldr w0, [sp,8]
cmp w0, 9
ble .L4
ldr w0, [sp,12]
add w0, w0, 1
str w0, [sp,12]
.L2:
ldr w0, [sp,12]
cmp w0, 9
ble .L5
mov w0, 0
add sp, sp, 16
ret

18.62: GCC 4.4.5 (MIPS) (IDA)


main:

var_18 = 0x18
var_10 = 0x10
var_C = 0xC
var_4 = 4

addiu $sp, 0x18


sw $fp, 0x18+var_4($sp)
move $fp, $sp
la $gp, __gnu_local_gp
sw $gp, 0x18+var_18($sp)
sw $zero, 0x18+var_C($fp)
b loc_A0
or $at, $zero

loc_24: # CODE XREF: main+AC


sw $zero, 0x18+var_10($fp)
b loc_7C
or $at, $zero

loc_30: # CODE XREF: main+88


lw $v0, 0x18+var_C($fp)
lw $a0, 0x18+var_10($fp)
lw $a1, 0x18+var_C($fp)
lw $v1, 0x18+var_10($fp)
or $at, $zero
mult $a1, $v1
mflo $a2
lw $v1, (tbl & 0xFFFF)($gp)
sll $v0, 1
sll $a1, $v0, 2
addu $v0, $a1
addu $v0, $a0
sll $v0, 2
addu $v0, $v1, $v0
sw $a2, 0($v0)
lw $v0, 0x18+var_10($fp)
or $at, $zero
addiu $v0, 1
sw $v0, 0x18+var_10($fp)

loc_7C: # CODE XREF: main+28


lw $v0, 0x18+var_10($fp)
or $at, $zero
slti $v0, 0xA
bnez $v0, loc_30
or $at, $zero
lw $v0, 0x18+var_C($fp)
or $at, $zero
addiu $v0, 1
sw $v0, 0x18+var_C($fp)

loc_A0: # CODE XREF: main+1C

314
18. 18.
lw $v0, 0x18+var_C($fp)
or $at, $zero
slti $v0, 0xA
bnez $v0, loc_24
or $at, $zero
move $v0, $zero
move $sp, $fp
lw $fp, 0x18+var_4($sp)
addiu $sp, 0x18
jr $ra
or $at, $zero

.comm tbl:0x64 # DATA XREF: main+4C

G.1.12 (. 989)

315
19. 19.

19

1 . ,
bool, .

19.1. -

19.1.1. x86

Win32 API:
HANDLE fh;

fh=CreateFile ("file", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS,


FILE_ATTRIBUTE_NORMAL, NULL);

(MSVC 2010):

19.1: MSVC 2010


push 0
push 128 ; 00000080H
push 4
push 0
push 1
push 1073741824 ; c0000000H
push OFFSET $SG78813
call DWORD PTR __imp__CreateFileA@28
mov DWORD PTR _fh$[ebp], eax

WinNT.h:

19.2: WinNT.h
#define GENERIC_READ (0x80000000L)
#define GENERIC_WRITE (0x40000000L)
#define GENERIC_EXECUTE (0x20000000L)
#define GENERIC_ALL (0x10000000L)

, GENERIC_READ | GENERIC_WRITE = 0x80000000 | 0x40000000 = 0xC0000000, -


CreateFile()2 .
CreateFile() ? KERNEL32.DLL Windows XP SP3 x86
CreateFileW() :

19.3: KERNEL32.DLL (Windows XP SP3 x86)


.text:7C83D429 test byte ptr [ebp+dwDesiredAccess+3], 40h
.text:7C83D42D mov [ebp+var_8], 1
.text:7C83D434 jz short loc_7C83D417
.text:7C83D436 jmp loc_7C810817

1 bit elds
2 msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx

316
19. 19.
TEST. , ,
(ebp+dwDesiredAccess+3) 0x40 ( GENERIC_WRITE). TEST
AND, ( CMP SUB,
(7.3.1 (. 80))).
:
if ((dwDesiredAccess&0x40000000) == 0) goto loc_7C83D417

AND , ZF JZ .
, dwDesiredAccess 0x40000000 AND 0,
ZF .
GCC 4.4.1 Linux:
#include <stdio.h>
#include <fcntl.h>

void main()
{
int handle;

handle=open ("file", O_RDWR | O_CREAT);


};

19.4: GCC 4.4.1


public main
main proc near

var_20 = dword ptr 20h


var_1C = dword ptr 1Ch
var_4 = dword ptr 4

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 20h
mov [esp+20h+var_1C], 42h
mov [esp+20h+var_20], offset aFile ; "file"
call _open
mov [esp+20h+var_4], eax
leave
retn
main endp

open() libc.so.6, :

19.5: open() (libc.so.6)


.text:000BE69B mov edx, [esp+4+mode] ; mode
.text:000BE69F mov ecx, [esp+4+flags] ; flags
.text:000BE6A3 mov ebx, [esp+4+filename] ; filename
.text:000BE6A7 mov eax, 5
.text:000BE6AC int 80h ; LINUX sys_open

, open() - Linux.
, Linux Linux , -
.
sys_open do_sys_open Linux 2.6.
do_filp_open() ( fs/namei.c).
N.B. ,
. fastcall (64.3 (. 690)). ,
, . GCC regparm3 ,
, .
3 ohse.de/uwe/articles/gcc-attributes.html#func-regparm

317
19. 19.
Linux 2.6 -mregparm=34 5 .
, EAX, EDX ECX,
. , , .
, 2.6.31, Ubuntu, IDA, do_filp_open().
- ( ):

19.6: do_lp_open() (linux kernel 2.6.31)


do_filp_open proc near
...
push ebp
mov ebp, esp
push edi
push esi
push ebx
mov ebx, ecx
add ebx, 1
sub esp, 98h
mov esi, [ebp+arg_4] ; acc_mode ( )
test bl, 3
mov [ebp+var_80], eax ; dfd ( )
mov [ebp+var_7C], edx ; pathname ( )
mov [ebp+var_78], ecx ; open_flag ( )
jnz short loc_C01EF684
mov ebx, ecx ; ebx < open_flag

GCC . , ,
, ( register allocator),
.
:

19.7: do_lp_open() (linux kernel 2.6.31)


loc_C01EF6B4: ; CODE XREF: do_filp_open+4F
test bl, 40h ; O_CREAT
jnz loc_C01EF810
mov edi, ebx
shr edi, 11h
xor edi, 1
and edi, 1
test ebx, 10000h
jz short loc_C01EF6D3
or edi, 2

0x40 O_CREAT. open_flag 0x40 1, -


JNZ .

19.1.2. ARM

Linux 3.8.0 O_CREAT .

19.8: linux kernel 3.8.0


struct file *do_filp_open(int dfd, struct filename *pathname,
const struct open_flags *op)
{
...
filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
...
}

static struct file *path_openat(int dfd, struct filename *pathname,


struct nameidata *nd, const struct open_flags *op, int flags)
{
...
4 kernelnewbies.org/Linux_2_6_20#head-042c62f290834eb1fe0a1942bbf5bb9a4accbc8f
5 . arch/x86/include/asm/calling.h

318
19. 19.
error = do_last(nd, &path, file, op, &opened, pathname);
...
}

static int do_last(struct nameidata *nd, struct path *path,


struct file *file, const struct open_flags *op,
int *opened, struct filename *name)
{
...
if (!(open_flag & O_CREAT)) {
...
error = lookup_fast(nd, path, &inode);
...
} else {
...
error = complete_walk(nd);
}
...
}

IDA, ARM:

19.9: do_last() (vmlinux)


...
.text:C0169EA8 MOV R9, R3 ; R3 (4th argument) open_flag
...
.text:C0169ED4 LDR R6, [R9] ; R6 open_flag
...
.text:C0169F68 TST R6, #0x40 ; jumptable C0169F00 default case
.text:C0169F6C BNE loc_C016A128
.text:C0169F70 LDR R2, [R4,#0x10]
.text:C0169F74 ADD R12, R4, #8
.text:C0169F78 LDR R3, [R4,#0xC]
.text:C0169F7C MOV R0, R4
.text:C0169F80 STR R12, [R11,#var_50]
.text:C0169F84 LDRB R3, [R2,R3]
.text:C0169F88 MOV R2, R8
.text:C0169F8C CMP R3, #0
.text:C0169F90 ORRNE R1, R1, #3
.text:C0169F94 STRNE R1, [R4,#0x24]
.text:C0169F98 ANDS R3, R6, #0x200000
.text:C0169F9C MOV R1, R12
.text:C0169FA0 LDRNE R3, [R4,#0x24]
.text:C0169FA4 ANDNE R3, R3, #1
.text:C0169FA8 EORNE R3, R3, #1
.text:C0169FAC STR R3, [R11,#var_54]
.text:C0169FB0 SUB R3, R11, #var_38
.text:C0169FB4 BL lookup_fast
...
.text:C016A128 loc_C016A128 ; CODE XREF: do_last.isra.14+DC
.text:C016A128 MOV R0, R4
.text:C016A12C BL complete_walk
...

TST TEST x86.


lookup_fast(),
complete_walk(). do_last().
O_CREAT 0x40.

19.2.
:
#include <stdio.h>

319
19. 19.
#define IS_SET(flag, bit) ((flag) & (bit))
#define SET_BIT(var, bit) ((var) |= (bit))
#define REMOVE_BIT(var, bit) ((var) &= ~(bit))

int f(int a)
{
int rt=a;

SET_BIT (rt, 0x4000);


REMOVE_BIT (rt, 0x200);

return rt;
};

int main()
{
f(0x12340678);
};

19.2.1. x86

MSVC

(MSVC 2010):

19.10: MSVC 2010


_rt$ = 4 ; size = 4
_a$ = 8 ; size = 4
_f PROC
push ebp
mov ebp, esp
push ecx
mov eax, DWORD PTR _a$[ebp]
mov DWORD PTR _rt$[ebp], eax
mov ecx, DWORD PTR _rt$[ebp]
or ecx, 16384 ; 00004000H
mov DWORD PTR _rt$[ebp], ecx
mov edx, DWORD PTR _rt$[ebp]
and edx, 513 ; fffffdffH
mov DWORD PTR _rt$[ebp], edx
mov eax, DWORD PTR _rt$[ebp]
mov esp, ebp
pop ebp
ret 0
_f ENDP

OR , .
AND . , AND , . ,
AND , , ,
( 0 ). .

320
19. 19.
OllyDbg

OllyDbg. , :
0x200 (00000000000000000001000000000) (.. 10- ( )).
0x200 0xFFFFFDFF (11111111111111111110111111111).
0x4000 (00000000000000100000000000000) (.. 15- ).
: 0x12340678 (10010001101000000011001111000). , :

. 19.1: OllyDbg: ECX

321
19. 19.
OR :

. 19.2: OllyDbg: OR

15- : 0x12344678 (10010001101000100011001111000).

322
19. 19.
( ):

. 19.3: OllyDbg: EDX

323
19. 19.
AND :

. 19.4: OllyDbg: AND

10- (, , 10-)
0x12344478 (10010001101000100010001111000).

MSVC

MSVC (/Ox), :
19.11: MSVC
_a$ = 8 ; size = 4
_f PROC
mov eax, DWORD PTR _a$[esp4]
and eax, 513 ; fffffdffH
or eax, 16384 ; 00004000H
ret 0
_f ENDP

GCC

GCC 4.4.1 :
19.12: GCC
public f
f proc near

var_4 = dword ptr 4


arg_0 = dword ptr 8

push ebp
mov ebp, esp
sub esp, 10h
mov eax, [ebp+arg_0]
mov [ebp+var_4], eax
or [ebp+var_4], 4000h
and [ebp+var_4], 0FFFFFDFFh
mov eax, [ebp+var_4]
leave
retn
f endp

, , MSVC .
GCC -O3:

324
19. 19.
GCC

19.13: GCC
public f
f proc near

arg_0 = dword ptr 8

push ebp
mov ebp, esp
mov eax, [ebp+arg_0]
pop ebp
or ah, 40h
and ah, 0FDh
retn
f endp

. , AH EAX. 8-
15- .
7 ( ) 6 5 4 3 2 1 0
RAXx64
EAX
AX
AH AL
N.B. 16- 8086 AX 8- AL (-
) AH (). 80386 32-, EAX,
, AX/ AH/ AL.
- , x86 16- 8086, 16-
32-. or ah, 40h 3 . or
eax, 04000h, 5 , 6 ( EAX).

GCC regparm

-O3, regparm=3,
, :

19.14: GCC
public f
f proc near
push ebp
or ah, 40h
mov ebp, esp
and ah, 0FDh
pop ebp
retn
f endp

EAX, . ,
(push ebp / mov ebp,esp) (pop ebp) ,
GCC . ,
inline- (43 (. 522)).

19.2.2. ARM + Keil 6/2013 ( ARM)

19.15: Keil 6/2013 ( ARM)


02 0C C0 E3 BIC R0, R0, #0x200
01 09 80 E3 ORR R0, R0, #0x4000
1E FF 2F E1 BX LR

BIC (BItwise bit Clear) . AND,


. .. NOT +AND.

325
19. 19.
ORR , OR x86.
.

19.2.3. ARM + Keil 6/2013 ( Thumb)

19.16: Keil 6/2013 ( Thumb)


01 21 89 03 MOVS R1, 0x4000
08 43 ORRS R0, R1
49 11 ASRS R1, R1, #5 ; generate 0x200 and place to R1
88 43 BICS R0, R1
70 47 BX LR

, Keil , Thumb, 0x200 0x4000, , , -


0x200 - .
ASRS ( ), 0x4000 5.

19.2.4. ARM + Xcode 4.6.3 (LLVM) ( ARM)

19.17: Xcode 4.6.3 (LLVM) ( ARM)


42 0C C0 E3 BIC R0, R0, #0x4200
01 09 80 E3 ORR R0, R0, #0x4000
1E FF 2F E1 BX LR

, LLVM, , , :
REMOVE_BIT (rt, 0x4200);
SET_BIT (rt, 0x4000);

. 0x4200? , LLVM6 . ,
, .
, (91 (. 899)).
Xcode 4.6.3 (LLVM) Thumb .

19.2.5. ARM: BIC

:
int f(int a)
{
int rt=a;

REMOVE_BIT (rt, 0x1234);

return rt;
};

Keil 5.03 ARM :


f PROC
BIC r0,r0,#0x1000
BIC r0,r0,#0x234
BX lr
ENDP

BIC, .. 0x1234 . BIC


0x1234, 0x1000 0x234.
6 LLVM build 2410.2.00 Apple Xcode 4.6.3

326
19. 19.
19.2.6. ARM64: GCC (Linaro) 4.9

GCC, ARM64, AND BIC:

19.18: GCC (Linaro) 4.9


f:
and w0, w0, 513 ; 0xFFFFFFFFFFFFFDFF
orr w0, w0, 16384 ; 0x4000
ret

19.2.7. ARM64: GCC (Linaro) 4.9

GCC , :

19.19: GCC (Linaro) 4.9


f:
sub sp, sp, #32
str w0, [sp,12]
ldr w0, [sp,12]
str w0, [sp,28]
ldr w0, [sp,28]
orr w0, w0, 16384 ; 0x4000
str w0, [sp,28]
ldr w0, [sp,28]
and w0, w0, 513 ; 0xFFFFFFFFFFFFFDFF
str w0, [sp,28]
ldr w0, [sp,28]
add sp, sp, 32
ret

19.2.8. MIPS

19.20: GCC 4.4.5 (IDA)


f:
; $a0=a
ori $a0, 0x4000
; $a0=a|0x4000
li $v0, 0xFFFFFDFF
jr $ra
and $v0, $a0, $v0
; : $v0 = $a0&$v0 = a|0x4000 & 0xFFFFFDFF

ORI , , , I .
, AND. ANDI, 0xFFFFFDFF
, 0xFFFFFDFF $V0,
AND, .

19.3.
/++ .
x86 SHL (SHift Left) SHR (SHift Right) .
- : 2n (.. 1, 2, 4, 8,
..): 16.1.2 (. 210), 16.2.1 (. 215).
,
.

327
19. 19.
19.4. : FPU
, oat IEEE 754:

31 30 23 22 0

( S )
MSB7 . , FPU-?
#include <stdio.h>

float my_abs (float i)


{
unsigned int tmp=(*(unsigned int*)&i) & 0x7FFFFFFF;
return *(float*)&tmp;
};

float set_sign (float i)


{
unsigned int tmp=(*(unsigned int*)&i) | 0x80000000;
return *(float*)&tmp;
};

float negate (float i)


{
unsigned int tmp=(*(unsigned int*)&i) ^ 0x80000000;
return *(float*)&tmp;
};

int main()
{
printf ("my_abs():\n");
printf ("%f\n", my_abs (123.456));
printf ("%f\n", my_abs (456.123));
printf ("set_sign():\n");
printf ("%f\n", set_sign (123.456));
printf ("%f\n", set_sign (456.123));
printf ("negate():\n");
printf ("%f\n", negate (123.456));
printf ("%f\n", negate (456.123));
};

/++ oat
. : my_abs() MSB; set_sign() MSB negate()
.

19.4.1. - XOR

XOR ( ) - () . -
, XOR 1 :

0 0 0
0 1 1
1 0 1
1 1 0
, XOR 0 , .. . XOR
.

19.4.2. x86

:
7 Most signicant bit/byte ( /)

328
19. 19.
19.21: MSVC 2012
_tmp$ = 8
_i$ = 8
_my_abs PROC
and DWORD PTR _i$[esp4], 2147483647 ; 7fffffffH
fld DWORD PTR _tmp$[esp4]
ret 0
_my_abs ENDP

_tmp$ = 8
_i$ = 8
_set_sign PROC
or DWORD PTR _i$[esp4], 2147483648 ; 80000000H
fld DWORD PTR _tmp$[esp4]
ret 0
_set_sign ENDP

_tmp$ = 8
_i$ = 8
_negate PROC
xor DWORD PTR _i$[esp4], 2147483648 ; 80000000H
fld DWORD PTR _tmp$[esp4]
ret 0
_negate ENDP

oat , .
AND OR . XOR .
ST0, .
MSVC 2012 x64:

19.22: MSVC 2012 x64


tmp$ = 8
i$ = 8
my_abs PROC
movss DWORD PTR [rsp+8], xmm0
mov eax, DWORD PTR i$[rsp]
btr eax, 31
mov DWORD PTR tmp$[rsp], eax
movss xmm0, DWORD PTR tmp$[rsp]
ret 0
my_abs ENDP
_TEXT ENDS

tmp$ = 8
i$ = 8
set_sign PROC
movss DWORD PTR [rsp+8], xmm0
mov eax, DWORD PTR i$[rsp]
bts eax, 31
mov DWORD PTR tmp$[rsp], eax
movss xmm0, DWORD PTR tmp$[rsp]
ret 0
set_sign ENDP

tmp$ = 8
i$ = 8
negate PROC
movss DWORD PTR [rsp+8], xmm0
mov eax, DWORD PTR i$[rsp]
btc eax, 31
mov DWORD PTR tmp$[rsp], eax
movss xmm0, DWORD PTR tmp$[rsp]
ret 0
negate ENDP

-, XMM0,
: BTR, BTS, BTC.

329
19. 19.
(BTR: reset), (BTS: set)
(BTC: complement). 31- MSB, .
, XMM0,
XMM0 Win64.

19.4.3. MIPS

GCC 4.4.5 MIPS :

19.23: GCC 4.4.5 (IDA)


my_abs:
; 1:
mfc1 $v1, $f12
li $v0, 0x7FFFFFFF
; $v0=0x7FFFFFFF
; :
and $v0, $v1
; 1:
mtc1 $v0, $f0
;
jr $ra
or $at, $zero ; branch delay slot

set_sign:
; 1:
mfc1 $v0, $f12
lui $v1, 0x8000
; $v1=0x80000000
; :
or $v0, $v1, $v0
; 1:
mtc1 $v0, $f0
;
jr $ra
or $at, $zero ; branch delay slot

negate:
; 1:
mfc1 $v0, $f12
lui $v1, 0x8000
; $v1=0x80000000
; :
xor $v0, $v1, $v0
; 1:
mtc1 $v0, $f0
;
jr $ra
or $at, $zero ; branch delay slot

0x80000000 LUI, LUI


16 , LUI ORI .

19.4.4. ARM

Keil 6/2013 ( ARM)

19.24: Keil 6/2013 ( ARM)


my_abs PROC
; :
BIC r0,r0,#0x80000000
BX lr
ENDP

set_sign PROC
; :

330
19. 19.
ORR r0,r0,#0x80000000
BX lr
ENDP

negate PROC
; :
EOR r0,r0,#0x80000000
BX lr
ENDP

. ARM BIC . EOR ARM


XOR (Exclusive OR).

Keil 6/2013 ( Thumb)

19.25: Keil 6/2013 ( Thumb)


my_abs PROC
LSLS r0,r0,#1
; r0=i<<1
LSRS r0,r0,#1
; r0=(i<<1)>>1
BX lr
ENDP

set_sign PROC
MOVS r1,#1
; r1=1
LSLS r1,r1,#31
; r1=1<<31=0x80000000
ORRS r0,r0,r1
; r0=r0 | 0x80000000
BX lr
ENDP

negate PROC
MOVS r1,#1
; r1=1
LSLS r1,r1,#31
; r1=1<<31=0x80000000
EORS r0,r0,r1
; r0=r0 ^ 0x80000000
BX lr
ENDP

Thumb 16- , , -
MOVS/ LSLS 0x80000000. : 1 << 31 = 0x80000000.
my_abs : (i << 1) >> 1. .
, input << 1, MSB ( ) .
result >> 1, , MSB ,
. , LSLS/ LSRS MSB.

GCC 4.6.3 (Raspberry Pi, ARM)

19.26: GCC 4.6.3 Raspberry Pi ( ARM)


my_abs
; S0 R2:
FMRS R2, S0
; :
BIC R3, R2, #0x80000000
; R3 S0:
FMSR S0, R3
BX LR

set_sign

331
19. 19.
; S0 R2:
FMRS R2, S0
; :
ORR R3, R2, #0x80000000
; R3 S0:
FMSR S0, R3
BX LR

negate
; S0 R2:
FMRS R2, S0
; :
ADD R3, R2, #0x80000000
; R3 S0:
FMSR S0, R3
BX LR

Raspberry Pi Linux QEMU FPU ARM, S-


R-.
FMRS GPR FPU .
my_abs() set_sign() , negate()? ADD XOR?
, ADD register, 0x80000000 XOR register, 0x80000000.
, ? , MSB ,
XOR. , 1000
3 . : 1234567 + 10000 = 1244567 ( 4 ).
, 0x80000000 100000000000000000000000000000000
, .. . 0x80000000 -
31 , MSB. 1 0 1. 1 1 10 , 32-
( ) , 32 . 0. XOR
ADD. , GCC , .

19.5.
, - .
population count8 .
#include <stdio.h>

#define IS_SET(flag, bit) ((flag) & (bit))

int f(unsigned int a)


{
int i;
int rt=0;

for (i=0; i<32; i++)


if (IS_SET (a, 1<<i))
rt++;

return rt;
};

int main()
{
f(0x12345678); // test
};

i 0 31, 1 i 1 0x80000000. , -
n . .. , 1 i
32- . .
1 i i = 0 . . . 31:
8 x86- ( SSE4) POPCNT

332
19. 19.
/++
10 1 1 1
11 21 2 2
12 22 4 4
13 23 8 8
14 24 16 0x10
15 25 32 0x20
16 26 64 0x40
17 27 128 0x80
18 28 256 0x100
19 29 512 0x200
1 10 210 1024 0x400
1 11 211 2048 0x800
1 12 212 4096 0x1000
1 13 213 8192 0x2000
1 14 214 16384 0x4000
1 15 215 32768 0x8000
1 16 216 65536 0x10000
1 17 217 131072 0x20000
1 18 218 262144 0x40000
1 19 219 524288 0x80000
1 20 220 1048576 0x100000
1 21 221 2097152 0x200000
1 22 222 4194304 0x400000
1 23 223 8388608 0x800000
1 24 224 16777216 0x1000000
1 25 225 33554432 0x2000000
1 26 226 67108864 0x4000000
1 27 227 134217728 0x8000000
1 28 228 268435456 0x10000000
1 29 229 536870912 0x20000000
1 30 230 1073741824 0x40000000
1 31 231 2147483648 0x80000000
- ( ), reverse engineer-,
. , , , -
.
. , ssl_private.h
Apache 2.4.6:
/**
* Define the SSL options
*/
#define SSL_OPT_NONE (0)
#define SSL_OPT_RELSET (1<<0)
#define SSL_OPT_STDENVVARS (1<<1)
#define SSL_OPT_EXPORTCERTDATA (1<<3)
#define SSL_OPT_FAKEBASICAUTH (1<<4)
#define SSL_OPT_STRICTREQUIRE (1<<5)
#define SSL_OPT_OPTRENEGOTIATE (1<<6)
#define SSL_OPT_LEGACYDNFORMAT (1<<7)

.
IS_SET a. IS_SET (AND)
0 , , . /++, if() ,
, 123456, .

19.5.1. x86

MSVC

(MSVC 2010):

333
19. 19.
19.27: MSVC 2010
_rt$ = 8 ; size = 4
_i$ = 4 ; size = 4
_a$ = 8 ; size = 4
_f PROC
push ebp
mov ebp, esp
sub esp, 8
mov DWORD PTR _rt$[ebp], 0
mov DWORD PTR _i$[ebp], 0
jmp SHORT $LN4@f
$LN3@f:
mov eax, DWORD PTR _i$[ebp] ; i
add eax, 1
mov DWORD PTR _i$[ebp], eax
$LN4@f:
cmp DWORD PTR _i$[ebp], 32 ; 00000020H
jge SHORT $LN2@f ; ?
mov edx, 1
mov ecx, DWORD PTR _i$[ebp]
shl edx, cl ; EDX=EDX<<CL
and edx, DWORD PTR _a$[ebp]
je SHORT $LN1@f ; AND 0?
;
mov eax, DWORD PTR _rt$[ebp] ; ,
add eax, 1 ; rt
mov DWORD PTR _rt$[ebp], eax
$LN1@f:
jmp SHORT $LN3@f
$LN2@f:
mov eax, DWORD PTR _rt$[ebp]
mov esp, ebp
pop ebp
ret 0
_f ENDP

334
19. 19.
OllyDbg

OllyDbg. 0x12345678.

i = 1, , i ECX:

. 19.5: OllyDbg: i = 1, i ECX

EDX 1. SHL.

335
19. 19.
SHL :

. 19.6: OllyDbg: i = 1, EDX =1 1 = 2

EDX 1 1 ( 2). .

336
19. 19.
AND ZF 1, , (0x12345678) 9 2 0:

. 19.7: OllyDbg: i = 1, ? . (ZF =1)

. , ,
: JZ .

337
19. 19.
i 4. SHL :

. 19.8: OllyDbg: i = 4, i ECX

338
19. 19.
EDX =1 4 ( 0x10 16):

. 19.9: OllyDbg: i = 4, EDX =1 4 = 0x10

339
19. 19.
AND :

. 19.10: OllyDbg: i = 4, ? . (ZF =0)

ZF 0 . , 0x12345678 & 0x10 = 0x10.


: .

13. 0x12345678.

GCC

GCC 4.4.1:

19.28: GCC 4.4.1


public f
f proc near

rt = dword ptr 0Ch


i = dword ptr 8
arg_0 = dword ptr 8

push ebp
mov ebp, esp
push ebx
sub esp, 10h
mov [ebp+rt], 0
mov [ebp+i], 0
jmp short loc_80483EF
loc_80483D0:
mov eax, [ebp+i]
mov edx, 1
mov ebx, edx
mov ecx, eax
shl ebx, cl
mov eax, ebx
and eax, [ebp+arg_0]
test eax, eax
jz short loc_80483EB
add [ebp+rt], 1
loc_80483EB:
add [ebp+i], 1
loc_80483EF:
cmp [ebp+i], 1Fh
jle short loc_80483D0
mov eax, [ebp+rt]
add esp, 10h
pop ebx

340
19. 19.
pop ebp
retn
f endp

19.5.2. x64

, 64- :
#include <stdio.h>
#include <stdint.h>

#define IS_SET(flag, bit) ((flag) & (bit))

int f(uint64_t a)
{
uint64_t i;
int rt=0;

for (i=0; i<64; i++)


if (IS_SET (a, 1ULL<<i))
rt++;

return rt;
};

GCC 4.8.2

19.29: GCC 4.8.2


f:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp24], rdi ; a
mov DWORD PTR [rbp12], 0 ; rt=0
mov QWORD PTR [rbp8], 0 ; i=0
jmp .L2
.L4:
mov rax, QWORD PTR [rbp8]
mov rdx, QWORD PTR [rbp24]
; RAX = i, RDX = a
mov ecx, eax
; ECX = i
shr rdx, cl
; RDX = RDX>>CL = a>>i
mov rax, rdx
; RAX = RDX = a>>i
and eax, 1
; EAX = EAX&1 = (a>>i)&1
test rax, rax
; ?
; ADD, .
je .L3
add DWORD PTR [rbp12], 1 ; rt++
.L3:
add QWORD PTR [rbp8], 1 ; i++
.L2:
cmp QWORD PTR [rbp8], 63 ; i<63?
jbe .L4 ; ,
mov eax, DWORD PTR [rbp12] ; rt
pop rbp
ret

341
19. 19.
GCC 4.8.2

19.30: GCC 4.8.2


1 f:
2 xor eax, eax ; rt EAX
3 xor ecx, ecx ; i ECX
4 .L3:
5 mov rsi, rdi ;
6 lea edx, [rax+1] ; EDX=EAX+1
7 ; EDX " rt", rt, 1
8 shr rsi, cl ; RSI=RSI>>CL
9 and esi, 1 ; ESI=ESI&1
10 ; 1? " rt" EAX
11 cmovne eax, edx
12 add rcx, 1 ; RCX++
13 cmp rcx, 64
14 jne .L3
15 rep ret ; AKA fatret

, . , ,
rt , rt 1
( 6), EDX. , 1, CMOVNE10 (
CMOVNZ11 ) rt EDX ( rt)
EAX ( rt ). ,
, .. 64 , .
, ( ) (-
rt ). CPU
: 33.1 (. 476).
REP RET ( F3 C3) FATRET MSVC.
RET, AMD , RET : [AMD13b,
p.15] 12 .

MSVC 2010

19.31: MSVC 2010


a$ = 8
f PROC
; RCX =
xor eax, eax
mov edx, 1
lea r8d, QWORD PTR [rax+64]
; R8D=64
npad 5
$LL4@f:
test rdx, rcx
; ?
; INC.
je SHORT $LN3@f
inc eax ; rt++
$LN3@f:
rol rdx, 1 ; RDX=RDX<<1
dec r8 ; R8
jne SHORT $LL4@f
fatret 0
f ENDP

ROL SHL, rotate left ( ) shift


left ( ), , , SHL.
: A.6.3 (. 971).
R8 64 0. i.
10 ConditionalMOVe if Not Equal (MOV )
11 ConditionalMOVe if Not Zero (MOV )
12 : http://go.yurichev.com/17328

342
19. 19.
:
RDX R8
0x0000000000000001 64
0x0000000000000002 63
0x0000000000000004 62
0x0000000000000008 61
... ...
0x4000000000000000 2
0x8000000000000000 1
FATRET, : 19.5.2 (. 342).

MSVC 2012

19.32: MSVC 2012


a$ = 8
f PROC
; RCX =
xor eax, eax
mov edx, 1
lea r8d, QWORD PTR [rax+32]
; EDX = 1, R8D = 32
npad 5
$LL4@f:
; 1 ----------------------------------
test rdx, rcx
je SHORT $LN3@f
inc eax ; rt++
$LN3@f:
rol rdx, 1 ; RDX=RDX<<1
;
; 2 ----------------------------------
test rdx, rcx
je SHORT $LN11@f
inc eax ; rt++
$LN11@f:
rol rdx, 1 ; RDX=RDX<<1
;
dec r8 ; R8
jne SHORT $LL4@f
fatret 0
f ENDP

MSVC 2012 MSVC 2010, -


2 32 64. , , . -
? , ? , , -
, , ,
.

19.5.3. ARM + Xcode 4.6.3 (LLVM) ( ARM)

19.33: Xcode 4.6.3 (LLVM) ( ARM)


MOV R1, R0
MOV R0, #0
MOV R2, #1
MOV R3, R0
loc_2E54
TST R1, R2,LSL R3 ; R1 & (R2<<R3)
ADD R3, R3, #1 ; R3++
ADDNE R0, R0, #1 ; ZF TST, R0++
CMP R3, #32
BNE loc_2E54
BX LR

343
19. 19.
TST TEST x86.
(41.2.1 (. 510)), ARM . ,
LSL (Logical Shift Left), LSR (Logical Shift Right), ASR (Arithmetic Shift Right), ROR (Rotate Right) RRX (Rotate Right with Extend)
, MOV, TST, CMP, ADD, SUB, RSB13 .
, , .
, TST R1, R2,LSL R3 R1 (R2 R3).

19.5.4. ARM + Xcode 4.6.3 (LLVM) ( Thumb-2)

, LSL.W/ TST TST, Thumb


LSL TST.
MOV R1, R0
MOVS R0, #0
MOV.W R9, #1
MOVS R3, #0
loc_2F7A
LSL.W R2, R9, R3
TST R2, R1
ADD.W R3, R3, #1
IT NE
ADDNE R0, #1
CMP R3, #32
BNE loc_2F7A
BX LR

19.5.5. ARM64 + GCC 4.9

64- , : 19.5.2 (. 341).

19.34: GCC (Linaro) 4.8


f:
mov w2, 0 ; rt=0
mov x5, 1
mov w1, w2
.L2:
lsl x4, x5, x1 ; w4 = w5<<w1 = 1<<i
add w3, w2, 1 ; new_rt=rt+1
tst x4, x0 ; (1<<i) & a
add w1, w1, 1 ; i++
; TST ?
; w2=w3 rt=new_rt.
; : w2=w2 rt=rt ( )
csel w2, w3, w2, ne
cmp w1, 64 ; i<64?
bne .L2 ;
mov w0, w2 ; rt
ret

, GCC x64: 19.30 (. 342).


CSEL Conditional SELect ( ). ,
TST W2, rt.

19.5.6. ARM64 + GCC 4.9

64- , : 19.5.2 (. 341).


, .
13 data processing instructions

344
19. 19.
19.35: GCC (Linaro) 4.8
f:
sub sp, sp, #32
str x0, [sp,8] ; "a" Register Save Area
str wzr, [sp,24] ; rt=0
str wzr, [sp,28] ; i=0
b .L2
.L4:
ldr w0, [sp,28]
mov x1, 1
lsl x0, x1, x0 ; X0 = X1<<X0 = 1<<i
mov x1, x0
; X1 = 1<<1
ldr x0, [sp,8]
; X0 = a
and x0, x1, x0
; X0 = X1&X0 = (1<<i) & a
; X0 ? .L3, "rt"
cmp x0, xzr
beq .L3
; rt++
ldr w0, [sp,24]
add w0, w0, 1
str w0, [sp,24]
.L3:
; i++
ldr w0, [sp,28]
add w0, w0, 1
str w0, [sp,28]
.L2:
; i<=63? .L4
ldr w0, [sp,28]
cmp w0, 63
ble .L4
; rt
ldr w0, [sp,24]
add sp, sp, 32
ret

19.5.7. MIPS

GCC

19.36: GCC 4.4.5 (IDA)


f:
; IDA , :
rt = 0x10
i = 0xC
var_4 = 4
a = 0

addiu $sp, 0x18


sw $fp, 0x18+var_4($sp)
move $fp, $sp
sw $a0, 0x18+a($fp)
; rt i :
sw $zero, 0x18+rt($fp)
sw $zero, 0x18+i($fp)
; :
b loc_68
or $at, $zero ; branch delay slot, NOP

loc_20:
li $v1, 1
lw $v0, 0x18+i($fp)
or $at, $zero ; load delay slot, NOP
sllv $v0, $v1, $v0

345
19. 19.
; $v0 = 1<<i
move $v1, $v0
lw $v0, 0x18+a($fp)
or $at, $zero ; load delay slot, NOP
and $v0, $v1, $v0
; $v0 = a&(1<<i)
; a&(1<<i) ? loc_58:
beqz $v0, loc_58
or $at, $zero
; , a&(1<<i)!=0, "rt":
lw $v0, 0x18+rt($fp)
or $at, $zero ; load delay slot, NOP
addiu $v0, 1
sw $v0, 0x18+rt($fp)

loc_58:
; i:
lw $v0, 0x18+i($fp)
or $at, $zero ; load delay slot, NOP
addiu $v0, 1
sw $v0, 0x18+i($fp)

loc_68:
; i 0x20 (32).
; loc_20, 0x20 (32):
lw $v0, 0x18+i($fp)
or $at, $zero ; load delay slot, NOP
slti $v0, 0x20 # ' '
bnez $v0, loc_20
or $at, $zero ; branch delay slot, NOP
; . rt:
lw $v0, 0x18+rt($fp)
move $sp, $fp ; load delay slot
lw $fp, 0x18+var_4($sp)
addiu $sp, 0x18 ; load delay slot
jr $ra
or $at, $zero ; branch delay slot, NOP

: ,
. SLLV Shift Word Left Logical Variable, SLL
SLL (, , ), SLL .

GCC

. . ? SLLV
, SLLV.
, : 33.1 (. 476).

19.37: GCC 4.4.5 (IDA)


f:
; $a0=a
; rt $v0:
move $v0, $zero
; i $v1:
move $v1, $zero
li $t0, 1
li $a3, 32
sllv $a1, $t0, $v1
; $a1 = $t0<<$v1 = 1<<i

loc_14:
and $a1, $a0
; $a1 = a&(1<<i)
; i:
addiu $v1, 1
; loc\_28 a&(1<<i)==0 rt:
beqz $a1, loc_28
addiu $a2, $v0, 1

346
19. 19.
; BEQZ , rt $v0:
move $v0, $a2

loc_28:
; i!=32, loc_14 :
bne $v1, $a3, loc_14
sllv $a1, $t0, $v1
;
jr $ra
or $at, $zero ; branch delay slot, NOP

19.6.
, /++ , x86 SHR/ SHL ( ), SAR/ SHL
( ).
ARM LSR/ LSL ( ), ASR/ LSL ( ).
( data processing instructions).

19.6.1. ( )

, 1000000 (0x40) :

19.38: /++
if (input&0x40)
...

19.39: x86
TEST REG, 40h
JNZ is_set
;

19.40: x86
TEST REG, 40h
JZ is_cleared
;

19.41: ARM ( ARM)


TST REG, #0x40
BNE is_set
;

AND TEST, .

19.6.2. ( )

/++ ( n ,
):

19.42: /++
if ((value>>n)&1)
....

x86- :

19.43: x86
; REG=input_value
; CL=n
SHR REG, CL
AND REG, 1

347
19. 19.
( 1 n , , ):
19.44: /++
if (value & (1<<n))
....

x86-:
19.45: x86
; CL=n
MOV REG, 1
SHL REG, CL
AND input_value, REG

19.6.3. ( )

19.46: /++
value=value|0x40;

19.47: x86
OR REG, 40h

19.48: ARM ( ARM) ARM64


ORR R0, R0, #0x40

19.6.4. ( )

19.49: /++
value=value|(1<<n);

x86-:
19.50: x86
; CL=n
MOV REG, 1
SHL REG, CL
OR input_value, REG

19.6.5. ( )

(AND) :
19.51: /++
value=value&(~0x40);

19.52: x86
AND REG, 0FFFFFFBFh

19.53: x64
AND REG, 0FFFFFFFFFFFFFFBFh

.
ARM ARM BIC, NOT +AND:
19.54: ARM ( ARM)
BIC R0, R0, #0x40

348
19. 19.
19.6.6. ( )

19.55: /++
value=value&(~(1<<n));

19.56: x86
; CL=n
MOV REG, 1
SHL REG, CL
NOT REG
AND input_value, REG

19.7.

19.7.1. #1

19.57: MSVC 2010


_a$ = 8
_f PROC
mov ecx, DWORD PTR _a$[esp4]
mov eax, ecx
mov edx, ecx
shl edx, 16 ; 00000010H
and eax, 65280 ; 0000ff00H
or eax, edx
mov edx, ecx
and edx, 16711680 ; 00ff0000H
shr ecx, 16 ; 00000010H
or edx, ecx
shl eax, 8
shr edx, 8
or eax, edx
ret 0
_f ENDP

19.58: Keil 6/2013 ( ARM)


f PROC
MOV r1,#0xff0000
AND r1,r1,r0,LSL #8
MOV r2,#0xff00
ORR r1,r1,r0,LSR #24
AND r2,r2,r0,LSR #8
ORR r1,r1,r2
ORR r0,r1,r0,LSL #24
BX lr
ENDP

19.59: Keil 6/2013 ( Thumb)


f PROC
MOVS r3,#0xff
LSLS r2,r0,#8
LSLS r3,r3,#16
ANDS r2,r2,r3
LSRS r1,r0,#24
ORRS r1,r1,r2
LSRS r2,r0,#8
ASRS r3,r3,#8
ANDS r2,r2,r3
ORRS r1,r1,r2
LSLS r0,r0,#24

349
19. 19.
ORRS r0,r0,r1
BX lr
ENDP

19.60: GCC 4.9 (ARM64)


f:
rev w0, w0
ret

19.61: GCC 4.4.5 (MIPS) (IDA)


f:
srl $v0, $a0, 24
sll $v1, $a0, 24
sll $a1, $a0, 8
or $v1, $v0
lui $v0, 0xFF
and $v0, $a1, $v0
srl $a0, 8
or $v0, $v1, $v0
andi $a0, 0xFF00
jr $ra
or $v0, $a0

: G.1.13 (. 989).

19.7.2. #2

19.62: MSVC 2010


_a$ = 8 ; size = 4
_f PROC
push esi
mov esi, DWORD PTR _a$[esp]
xor ecx, ecx
push edi
lea edx, DWORD PTR [ecx+1]
xor eax, eax
npad 3 ; align next label
$LL3@f:
mov edi, esi
shr edi, cl
add ecx, 4
and edi, 15
imul edi, edx
lea edx, DWORD PTR [edx+edx*4]
add eax, edi
add edx, edx
cmp ecx, 28
jle SHORT $LL3@f
pop edi
pop esi
ret 0
_f ENDP

19.63: Keil 6/2013 ( ARM)


f PROC
MOV r3,r0
MOV r1,#0
MOV r2,#1
MOV r0,r1
|L0.16|
LSR r12,r3,r1
AND r12,r12,#0xf
MLA r0,r12,r2,r0

350
19. 19.
ADD r1,r1,#4
ADD r2,r2,r2,LSL #2
CMP r1,#0x1c
LSL r2,r2,#1
BLE |L0.16|
BX lr
ENDP

19.64: Keil 6/2013 ( Thumb)


f PROC
PUSH {r4,lr}
MOVS r3,r0
MOVS r1,#0
MOVS r2,#1
MOVS r0,r1
|L0.10|
MOVS r4,r3
LSRS r4,r4,r1
LSLS r4,r4,#28
LSRS r4,r4,#28
MULS r4,r2,r4
ADDS r0,r4,r0
MOVS r4,#0xa
MULS r2,r4,r2
ADDS r1,r1,#4
CMP r1,#0x1c
BLE |L0.10|
POP {r4,pc}
ENDP

19.65: GCC 4.9 (ARM64)


f:
sub sp, sp, #32
str w0, [sp,12]
str wzr, [sp,28]
mov w0, 1
str w0, [sp,24]
str wzr, [sp,20]
b .L2
.L3:
ldr w0, [sp,28]
ldr w1, [sp,12]
lsr w0, w1, w0
and w1, w0, 15
ldr w0, [sp,24]
mul w0, w1, w0
ldr w1, [sp,20]
add w0, w1, w0
str w0, [sp,20]
ldr w0, [sp,28]
add w0, w0, 4
str w0, [sp,28]
ldr w1, [sp,24]
mov w0, w1
lsl w0, w0, 2
add w0, w0, w1
lsl w0, w0, 1
str w0, [sp,24]
.L2:
ldr w0, [sp,28]
cmp w0, 28
ble .L3
ldr w0, [sp,20]
add sp, sp, 32
ret

19.66: GCC 4.4.5 (MIPS) (IDA)

351
19. 19.
f:
srl $v0, $a0, 8
srl $a3, $a0, 20
andi $a3, 0xF
andi $v0, 0xF
srl $a1, $a0, 12
srl $a2, $a0, 16
andi $a1, 0xF
andi $a2, 0xF
sll $t2, $v0, 4
sll $v1, $a3, 2
sll $t0, $v0, 2
srl $t1, $a0, 4
sll $t5, $a3, 7
addu $t0, $t2
subu $t5, $v1
andi $t1, 0xF
srl $v1, $a0, 28
sll $t4, $a1, 7
sll $t2, $a2, 2
sll $t3, $a1, 2
sll $t7, $a2, 7
srl $v0, $a0, 24
addu $a3, $t5, $a3
subu $t3, $t4, $t3
subu $t7, $t2
andi $v0, 0xF
sll $t5, $t1, 3
sll $t6, $v1, 8
sll $t2, $t0, 2
sll $t4, $t1, 1
sll $t1, $v1, 3
addu $a2, $t7, $a2
subu $t1, $t6, $t1
addu $t2, $t0, $t2
addu $t4, $t5
addu $a1, $t3, $a1
sll $t5, $a3, 2
sll $t3, $v0, 8
sll $t0, $v0, 3
addu $a3, $t5
subu $t0, $t3, $t0
addu $t4, $t2, $t4
sll $t3, $a2, 2
sll $t2, $t1, 6
sll $a1, 3
addu $a1, $t4, $a1
subu $t1, $t2, $t1
addu $a2, $t3
sll $t2, $t0, 6
sll $t3, $a3, 2
andi $a0, 0xF
addu $v1, $t1, $v1
addu $a0, $a1
addu $a3, $t3
subu $t0, $t2, $t0
sll $a2, 4
addu $a2, $a0, $a2
addu $v0, $t0, $v0
sll $a1, $v1, 2
sll $a3, 5
addu $a3, $a2, $a3
addu $v1, $a1
sll $v0, 6
addu $v0, $a3, $v0
sll $v1, 7
jr $ra
addu $v0, $v1, $v0

: G.1.13 (. 989).

352
19. 19.
19.7.3. #3

MSDN14 , , win32- MessageBox().

19.67: MSVC 2010


_main PROC
push 278595 ; 00044043H
push OFFSET $SG79792 ; 'caption'
push OFFSET $SG79793 ; 'hello, world!'
push 0
call DWORD PTR __imp__MessageBoxA@16
xor eax, eax
ret 0
_main ENDP

: G.1.13 (. 989).

19.7.4. #4

19.68: MSVC 2010


_m$ = 8 ; size = 4
_n$ = 12 ; size = 4
_f PROC
mov ecx, DWORD PTR _n$[esp4]
xor eax, eax
xor edx, edx
test ecx, ecx
je SHORT $LN2@f
push esi
mov esi, DWORD PTR _m$[esp]
$LL3@f:
test cl, 1
je SHORT $LN1@f
add eax, esi
adc edx, 0
$LN1@f:
add esi, esi
shr ecx, 1
jne SHORT $LL3@f
pop esi
$LN2@f:
ret 0
_f ENDP

19.69: Keil 6/2013 ( ARM)


f PROC
PUSH {r4,lr}
MOV r3,r0
MOV r0,#0
MOV r2,r0
MOV r12,r0
B |L0.48|
|L0.24|
TST r1,#1
BEQ |L0.40|
ADDS r0,r0,r3
ADC r2,r2,r12
|L0.40|
LSL r3,r3,#1
LSR r1,r1,#1
|L0.48|
CMP r1,#0
MOVEQ r1,r2
14 Microsoft Developer Network

353
19. 19.
BNE |L0.24|
POP {r4,pc}
ENDP

19.70: Keil 6/2013 ( Thumb)


f PROC
PUSH {r4,r5,lr}
MOVS r3,r0
MOVS r0,#0
MOVS r2,r0
MOVS r4,r0
B |L0.24|
|L0.12|
LSLS r5,r1,#31
BEQ |L0.20|
ADDS r0,r0,r3
ADCS r2,r2,r4
|L0.20|
LSLS r3,r3,#1
LSRS r1,r1,#1
|L0.24|
CMP r1,#0
BNE |L0.12|
MOVS r1,r2
POP {r4,r5,pc}
ENDP

19.71: GCC 4.9 (ARM64)


f:
mov w2, w0
mov x0, 0
cbz w1, .L2
.L3:
and w3, w1, 1
lsr w1, w1, 1
cmp w3, wzr
add x3, x0, x2, uxtw
lsl w2, w2, 1
csel x0, x3, x0, ne
cbnz w1, .L3
.L2:
ret

19.72: GCC 4.4.5 (MIPS) (IDA)


mult:
beqz $a1, loc_40
move $a3, $zero
move $a2, $zero
addu $t0, $a3, $a0

loc_10: # CODE XREF: mult+38


sltu $t1, $t0, $a3
move $v1, $t0
andi $t0, $a1, 1
addu $t1, $a2
beqz $t0, loc_30
srl $a1, 1
move $a3, $v1
move $a2, $t1

loc_30: # CODE XREF: mult+20


beqz $a1, loc_44
sll $a0, 1
b loc_10
addu $t0, $a3, $a0
loc_40: # CODE XREF: mult
move $a2, $zero

354
19. 19.

loc_44: # CODE XREF: mult:loc_30


move $v0, $a2
jr $ra
move $v1, $a3

: G.1.13 (. 990).

355
20. 20.

20

, , .
1 , ( , ),
.
#include <stdint.h>

// Numerical Recipes
#define RNG_a 1664525
#define RNG_c 1013904223

static uint32_t rand_state;

void my_srand (uint32_t init)


{
rand_state=init;
}

int my_rand ()
{
rand_state=rand_state*RNG_a;
rand_state=rand_state+RNG_c;
return rand_state & 0x7fff;
}

: ,
.
. [Pre+07].
/++ #define. . /++ ,
/++ . , ,
. ( ) -,
.
, my_rand()
0..32767. 32- , .

20.1. x86

20.1: MSVC 2013


_BSS SEGMENT
_rand_state DD 01H DUP (?)
_BSS ENDS

_init$ = 8
_srand PROC
1

356
20. 20.
mov eax, DWORD PTR _init$[esp4]
mov DWORD PTR _rand_state, eax
ret 0
_srand ENDP

_TEXT SEGMENT
_rand PROC
imul eax, DWORD PTR _rand_state, 1664525
add eax, 1013904223 ; 3c6ef35fH
mov DWORD PTR _rand_state, eax
and eax, 32767 ; 00007fffH
ret 0
_rand ENDP

_TEXT ENDS

: . . my_srand()
rand_state.
my_rand() , rand_state, EAX.
:

20.2: MSVC 2013


_BSS SEGMENT
_rand_state DD 01H DUP (?)
_BSS ENDS

_init$ = 8
_srand PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _init$[ebp]
mov DWORD PTR _rand_state, eax
pop ebp
ret 0
_srand ENDP

_TEXT SEGMENT
_rand PROC
push ebp
mov ebp, esp
imul eax, DWORD PTR _rand_state, 1664525
mov DWORD PTR _rand_state, eax
mov ecx, DWORD PTR _rand_state
add ecx, 1013904223 ; 3c6ef35fH
mov DWORD PTR _rand_state, ecx
mov eax, DWORD PTR _rand_state
and eax, 32767 ; 00007fffH
pop ebp
ret 0
_rand ENDP

_TEXT ENDS

20.2. x64
x64 , 32- 64- (
int). my_srand() ECX, :

20.3: MSVC 2013 x64


_BSS SEGMENT
rand_state DD 01H DUP (?)
_BSS ENDS

init$ = 8
my_srand PROC

357
20. 20.
; ECX =
mov DWORD PTR rand_state, ecx
ret 0
my_srand ENDP

_TEXT SEGMENT
my_rand PROC
imul eax, DWORD PTR rand_state, 1664525 ; 0019660dH
add eax, 1013904223 ; 3c6ef35fH
mov DWORD PTR rand_state, eax
and eax, 32767 ; 00007fffH
ret 0
my_rand ENDP

_TEXT ENDS

GCC .

20.3. 32-bit ARM

20.4: Keil 6/2013 ( ARM)


my_srand PROC
LDR r1,|L0.52| ; rand_state
STR r0,[r1,#0] ; rand_state
BX lr
ENDP

my_rand PROC
LDR r0,|L0.52| ; rand_state
LDR r2,|L0.56| ; RNG_a
LDR r1,[r0,#0] ; rand_state
MUL r1,r2,r1
LDR r2,|L0.60| ; RNG_c
ADD r1,r1,r2
STR r1,[r0,#0] ; rand_state
; AND 0x7FFF:
LSL r0,r1,#17
LSR r0,r0,#17
BX lr
ENDP

|L0.52|
DCD ||.data||
|L0.56|
DCD 0x0019660d
|L0.60|
DCD 0x3c6ef35f

AREA ||.data||, DATA, ALIGN=2

rand_state
DCD 0x00000000

ARM 32- , Keil- -


.
: 0x7FFF . Keil rand_state 17
17 . /++- (rand_state 17) 17. -
, , 17 , 15 ,
, .

Keil Thumb .

20.4. MIPS

358
20. 20.
20.5: GCC 4.4.5 (IDA)
my_srand:
; $a0 rand_state:
lui $v0, (rand_state >> 16)
jr $ra
sw $a0, rand_state
my_rand:
; rand_state $v0:
lui $v1, (rand_state >> 16)
lw $v0, rand_state
or $at, $zero ; load delay slot
; rand_state $v0 1664525 (RNG_a):
sll $a1, $v0, 2
sll $a0, $v0, 4
addu $a0, $a1, $a0
sll $a1, $a0, 6
subu $a0, $a1, $a0
addu $a0, $v0
sll $a1, $a0, 5
addu $a0, $a1
sll $a0, 3
addu $v0, $a0, $v0
sll $a0, $v0, 2
addu $v0, $a0
; 1013904223 (RNG_c)
; LI IDA LUI ORI
li $a0, 0x3C6EF35F
addu $v0, $a0
; rand_state:
sw $v0, (rand_state & 0xFFFF)($v1)
jr $ra
andi $v0, 0x7FFF ; branch delay slot

, (0x3C6EF35F 1013904223). (1664525)?


, 1664525 ! :
#define RNG_a 1664525

int f (int a)
{
return a*RNG_a;
}

20.6: GCC 4.4.5 (IDA)


f:
sll $v1, $a0, 2
sll $v0, $a0, 4
addu $v0, $v1, $v0
sll $v1, $v0, 6
subu $v0, $v1, $v0
addu $v0, $a0
sll $v1, $v0, 5
addu $v0, $v1
sll $v0, 3
addu $a0, $v0, $a0
sll $v0, $a0, 2
jr $ra
addu $v0, $a0, $v0 ; branch delay slot

20.4.1. MIPS (relocs)

, .
IDA, .
objdump : :

359
20. 20.
20.7: GCC 4.4.5 (objdump)
# objdump D rand_O3.o

...

00000000 <my_srand>:
0: 3c020000 lui v0,0x0
4: 03e00008 jr ra
8: ac440000 sw a0,0(v0)

0000000c <my_rand>:
c: 3c030000 lui v1,0x0
10: 8c620000 lw v0,0(v1)
14: 00200825 move at,at
18: 00022880 sll a1,v0,0x2
1c: 00022100 sll a0,v0,0x4
20: 00a42021 addu a0,a1,a0
24: 00042980 sll a1,a0,0x6
28: 00a42023 subu a0,a1,a0
2c: 00822021 addu a0,a0,v0
30: 00042940 sll a1,a0,0x5
34: 00852021 addu a0,a0,a1
38: 000420c0 sll a0,a0,0x3
3c: 00821021 addu v0,a0,v0
40: 00022080 sll a0,v0,0x2
44: 00441021 addu v0,v0,a0
48: 3c043c6e lui a0,0x3c6e
4c: 3484f35f ori a0,a0,0xf35f
50: 00441021 addu v0,v0,a0
54: ac620000 sw v0,0(v1)
58: 03e00008 jr ra
5c: 30427fff andi v0,v0,0x7fff

...

# objdump r rand_O3.o

...

RELOCATION RECORDS FOR [.text]:


OFFSET TYPE VALUE
00000000 R_MIPS_HI16 .bss
00000008 R_MIPS_LO16 .bss
0000000c R_MIPS_HI16 .bss
00000010 R_MIPS_LO16 .bss
00000054 R_MIPS_LO16 .bss

...

my_srand(). , 0, R_MIPS_HI16, ,
8, R_MIPS_LO16. , .bss 0
( ) 8 ( ). rand_state
.bss. LUI SW
, . LUI
SW. SW
$V0 ( ).
my_rand(): R_MIPS_HI16
.bss LUI. rand_state $V1. -
LW 0x10 rand_state
$V1. SW 0x54
rand_state.
IDA , . .

360
20. 20.
20.5.
: 65.1 (. 697).

361
21. 21.

21

, /++ , , , -
, , 1 .

21.1. MSVC: SYSTEMTIME


, , SYSTEMTIME2 win32 .
:

21.1: WinBase.h
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME;

:
#include <windows.h>
#include <stdio.h>

void main()
{
SYSTEMTIME t;
GetSystemTime (&t);

printf ("%04d%02d%02d %02d:%02d:%02d\n",


t.wYear, t.wMonth, t.wDay,
t.wHour, t.wMinute, t.wSecond);

return;
};

(MSVC 2010):

21.2: MSVC 2010 /GS-


_t$ = 16 ; size = 16
_main PROC
push ebp
mov ebp, esp
sub esp, 16
lea eax, DWORD PTR _t$[ebp]
1 AKA
2 MSDN: SYSTEMTIME structure

362
21. 21.
push eax
call DWORD PTR __imp__GetSystemTime@4
movzx ecx, WORD PTR _t$[ebp+12] ; wSecond
push ecx
movzx edx, WORD PTR _t$[ebp+10] ; wMinute
push edx
movzx eax, WORD PTR _t$[ebp+8] ; wHour
push eax
movzx ecx, WORD PTR _t$[ebp+6] ; wDay
push ecx
movzx edx, WORD PTR _t$[ebp+2] ; wMonth
push edx
movzx eax, WORD PTR _t$[ebp] ; wYear
push eax
push OFFSET $SG78811 ; '%04d%02d%02d %02d:%02d:%02d', 0aH, 00H
call _printf
add esp, 28
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP

16 sizeof(WORD)*8 ( 8
WORD).
, wYear. ,
GetSystemTime()3 SYSTEMTIME, ,
wYear, ! GetSystemTime() WORD
, 2 , , .., ..

3 MSDN: GetSystemTime function

363
21. 21.
21.1.1. OllyDbg

MSVC 2010 /GS- /MD OllyDbg.


, GetSystemTime(),
, :

. 21.1: OllyDbg: GetSystemTime()

, , 9 2014, 22:29:52:

. 21.2: OllyDbg: printf()

, 16 :
DE 07 0C 00 02 00 09 00 16 00 1D 00 34 00 D4 03

. (endianness) little endian,


, . , 16- :

0x07DE 2014 wYear
0x000C 12 wMonth
0x0002 2 wDayOfWeek
0x0009 9 wDay
0x0016 22 wHour
0x001D 29 wMinute
0x0034 52 wSecond
0x03D4 980 wMilliseconds
, , 32- .
printf() .
printf() (wDayOfWeek wMilliseconds),
.

21.1.2.

, ,
. SYSTEMTIME, :

364
21. 21.

#include <windows.h>
#include <stdio.h>

void main()
{
WORD array[8];
GetSystemTime (array);

printf ("%04d%02d%02d %02d:%02d:%02d\n",


array[0] /* wYear */, array[1] /* wMonth */, array[3] /* wDay */,
array[4] /* wHour */, array[5] /* wMinute */, array[6] /* wSecond */);

return;
};

:
systemtime2.c(7) : warning C4133: 'function' : incompatible types from 'WORD [8]' to 'LPSYSTEMTIME'

, :

21.3: MSVC 2010


$SG78573 DB '%04d%02d%02d %02d:%02d:%02d', 0aH, 00H

_array$ = 16 ; size = 16
_main PROC
push ebp
mov ebp, esp
sub esp, 16
lea eax, DWORD PTR _array$[ebp]
push eax
call DWORD PTR __imp__GetSystemTime@4
movzx ecx, WORD PTR _array$[ebp+12] ; wSecond
push ecx
movzx edx, WORD PTR _array$[ebp+10] ; wMinute
push edx
movzx eax, WORD PTR _array$[ebp+8] ; wHoure
push eax
movzx ecx, WORD PTR _array$[ebp+6] ; wDay
push ecx
movzx edx, WORD PTR _array$[ebp+2] ; wMonth
push edx
movzx eax, WORD PTR _array$[ebp] ; wYear
push eax
push OFFSET $SG78573
call _printf
add esp, 28
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP

!
. , ,
, , .
, . . , ,
, , ..
OllyDbg , , .

21.2. malloc()
, , , :

365
21. 21.

#include <windows.h>
#include <stdio.h>

void main()
{
SYSTEMTIME *t;

t=(SYSTEMTIME *)malloc (sizeof (SYSTEMTIME));

GetSystemTime (t);

printf ("%04d%02d%02d %02d:%02d:%02d\n",


t>wYear, t>wMonth, t>wDay,
t>wHour, t>wMinute, t>wSecond);

free (t);

return;
};

(/Ox) , .

21.4: MSVC
_main PROC
push esi
push 16
call _malloc
add esp, 4
mov esi, eax
push esi
call DWORD PTR __imp__GetSystemTime@4
movzx eax, WORD PTR [esi+12] ; wSecond
movzx ecx, WORD PTR [esi+10] ; wMinute
movzx edx, WORD PTR [esi+8] ; wHour
push eax
movzx eax, WORD PTR [esi+6] ; wDay
push ecx
movzx ecx, WORD PTR [esi+2] ; wMonth
push edx
movzx edx, WORD PTR [esi] ; wYear
push eax
push ecx
push edx
push OFFSET $SG78833
call _printf
push esi
call _free
add esp, 32
xor eax, eax
pop esi
ret 0
_main ENDP

, sizeof(SYSTEMTIME) = 16, malloc().


EAX, ESI. Win32 GetSystemTime() -
ESI,
GetSystemTime().
MOVZX (Move with Zero eXtend). MOVSX, -
0. , printf() 32- int, WORD 16- -
. WORD int, 16 31,
, .
8- WORD-:
#include <windows.h>
#include <stdio.h>

void main()

366
21. 21.
{
WORD *t;

t=(WORD *)malloc (16);

GetSystemTime (t);

printf ("%04d%02d%02d %02d:%02d:%02d\n",


t[0] /* wYear */, t[1] /* wMonth */, t[3] /* wDay */,
t[4] /* wHour */, t[5] /* wMinute */, t[6] /* wSecond */);

free (t);

return;
};

21.5: MSVC
$SG78594 DB '%04d%02d%02d %02d:%02d:%02d', 0aH, 00H

_main PROC
push esi
push 16
call _malloc
add esp, 4
mov esi, eax
push esi
call DWORD PTR __imp__GetSystemTime@4
movzx eax, WORD PTR [esi+12]
movzx ecx, WORD PTR [esi+10]
movzx edx, WORD PTR [esi+8]
push eax
movzx eax, WORD PTR [esi+6]
push ecx
movzx ecx, WORD PTR [esi+2]
push edx
movzx edx, WORD PTR [esi]
push eax
push ecx
push edx
push OFFSET $SG78594
call _printf
push esi
call _free
add esp, 32
xor eax, eax
pop esi
ret 0
_main ENDP

, . ,
, , .

21.3. UNIX: struct tm

21.3.1. Linux

, , tm time.h:
#include <stdio.h>
#include <time.h>

void main()
{
struct tm t;
time_t unix_time;

367
21. 21.

unix_time=time(NULL);

localtime_r (&unix_time, &t);

printf ("Year: %d\n", t.tm_year+1900);


printf ("Month: %d\n", t.tm_mon);
printf ("Day: %d\n", t.tm_mday);
printf ("Hour: %d\n", t.tm_hour);
printf ("Minutes: %d\n", t.tm_min);
printf ("Seconds: %d\n", t.tm_sec);
};

GCC 4.4.1:

21.6: GCC 4.4.1


main proc near
push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 40h
mov dword ptr [esp], 0 ; time()
call time
mov [esp+3Ch], eax
lea eax, [esp+3Ch] ; time()
lea edx, [esp+10h] ; ESP+10h struct tm
mov [esp+4], edx ;
mov [esp], eax ; time()
call localtime_r
mov eax, [esp+24h] ; tm_year
lea edx, [eax+76Ch] ; edx=eax+1900
mov eax, offset format ; "Year: %d\n"
mov [esp+4], edx
mov [esp], eax
call printf
mov edx, [esp+20h] ; tm_mon
mov eax, offset aMonthD ; "Month: %d\n"
mov [esp+4], edx
mov [esp], eax
call printf
mov edx, [esp+1Ch] ; tm_mday
mov eax, offset aDayD ; "Day: %d\n"
mov [esp+4], edx
mov [esp], eax
call printf
mov edx, [esp+18h] ; tm_hour
mov eax, offset aHourD ; "Hour: %d\n"
mov [esp+4], edx
mov [esp], eax
call printf
mov edx, [esp+14h] ; tm_min
mov eax, offset aMinutesD ; "Minutes: %d\n"
mov [esp+4], edx
mov [esp], eax
call printf
mov edx, [esp+10h]
mov eax, offset aSecondsD ; "Seconds: %d\n"
mov [esp+4], edx ; tm_sec
mov [esp], eax
call printf
leave
retn
main endp

, - , IDA .
:-) .
lea edx, [eax+76Ch] 0x76C (1900) EAX,
. . LEA (A.6.2 (. 965)).

368
21. 21.
GDB

GDB 4 :

21.7: GDB
dennis@ubuntuvm:~/polygon$ date
Mon Jun 2 18:10:37 EEST 2014
dennis@ubuntuvm:~/polygon$ gcc GCC_tm.c o GCC_tm
dennis@ubuntuvm:~/polygon$ gdb GCC_tm
GNU gdb (GDB) 7.6.1ubuntu
Copyright (C) 2013 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 "i686linuxgnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dennis/polygon/GCC_tm...(no debugging symbols found)...done.
(gdb) b printf
Breakpoint 1 at 0x8048330
(gdb) run
Starting program: /home/dennis/polygon/GCC_tm

Breakpoint 1, __printf (format=0x80485c0 "Year: %d\n") at printf.c:29


29 printf.c: No such file or directory.
(gdb) x/20x $esp
0xbffff0dc: 0x080484c3 0x080485c0 0x000007de 0x00000000
0xbffff0ec: 0x08048301 0x538c93ed 0x00000025 0x0000000a
0xbffff0fc: 0x00000012 0x00000002 0x00000005 0x00000072
0xbffff10c: 0x00000001 0x00000098 0x00000001 0x00002a30
0xbffff11c: 0x0804b090 0x08048530 0x00000000 0x00000000
(gdb)

. , , time.h:

21.8: time.h
struct tm
{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};

32- int WORD SYSTEMTIME. , 32-


.
:
0xbffff0dc: 0x080484c3 0x080485c0 0x000007de 0x00000000
0xbffff0ec: 0x08048301 0x538c93ed 0x00000025 sec 0x0000000a min
0xbffff0fc: 0x00000012 hour 0x00000002 mday 0x00000005 mon 0x00000072 year
0xbffff10c: 0x00000001 wday 0x00000098 yday 0x00000001 isdst0x00002a30
0xbffff11c: 0x0804b090 0x08048530 0x00000000 0x00000000

, :
4 date . , , GDB,

369
21. 21.

0x00000025 37 tm_sec
0x0000000a 10 tm_min
0x00000012 18 tm_hour
0x00000002 2 tm_mday
0x00000005 5 tm_mon
0x00000072 114 tm_year
0x00000001 1 tm_wday
0x00000098 152 tm_yday
0x00000001 1 tm_isdst
SYSTEMTIME (21.1 (. 362)), , ,
, , tm_wday, tm_yday, tm_isdst.

21.3.2. ARM

Keil 6/2013 ( Thumb)

21.9: Keil 6/2013 ( Thumb)


var_38 = 0x38
var_34 = 0x34
var_30 = 0x30
var_2C = 0x2C
var_28 = 0x28
var_24 = 0x24
timer = 0xC

PUSH {LR}
MOVS R0, #0 ; timer
SUB SP, SP, #0x34
BL time
STR R0, [SP,#0x38+timer]
MOV R1, SP ; tp
ADD R0, SP, #0x38+timer ; timer
BL localtime_r
LDR R1, =0x76C
LDR R0, [SP,#0x38+var_24]
ADDS R1, R0, R1
ADR R0, aYearD ; "Year: %d\n"
BL __2printf
LDR R1, [SP,#0x38+var_28]
ADR R0, aMonthD ; "Month: %d\n"
BL __2printf
LDR R1, [SP,#0x38+var_2C]
ADR R0, aDayD ; "Day: %d\n"
BL __2printf
LDR R1, [SP,#0x38+var_30]
ADR R0, aHourD ; "Hour: %d\n"
BL __2printf
LDR R1, [SP,#0x38+var_34]
ADR R0, aMinutesD ; "Minutes: %d\n"
BL __2printf
LDR R1, [SP,#0x38+var_38]
ADR R0, aSecondsD ; "Seconds: %d\n"
BL __2printf
ADD SP, SP, #0x34
POP {PC}

Xcode 4.6.3 (LLVM) ( Thumb-2)

IDA tm ( IDA , localtime_r()),


.

370
21. 21.
21.10: Xcode 4.6.3 (LLVM) ( Thumb-2)
var_38 = 0x38
var_34 = 0x34

PUSH {R7,LR}
MOV R7, SP
SUB SP, SP, #0x30
MOVS R0, #0 ; time_t *
BLX _time
ADD R1, SP, #0x38+var_34 ; struct tm *
STR R0, [SP,#0x38+var_38]
MOV R0, SP ; time_t *
BLX _localtime_r
LDR R1, [SP,#0x38+var_34.tm_year]
MOV R0, 0xF44 ; "Year: %d\n"
ADD R0, PC ; char *
ADDW R1, R1, #0x76C
BLX _printf
LDR R1, [SP,#0x38+var_34.tm_mon]
MOV R0, 0xF3A ; "Month: %d\n"
ADD R0, PC ; char *
BLX _printf
LDR R1, [SP,#0x38+var_34.tm_mday]
MOV R0, 0xF35 ; "Day: %d\n"
ADD R0, PC ; char *
BLX _printf
LDR R1, [SP,#0x38+var_34.tm_hour]
MOV R0, 0xF2E ; "Hour: %d\n"
ADD R0, PC ; char *
BLX _printf
LDR R1, [SP,#0x38+var_34.tm_min]
MOV R0, 0xF28 ; "Minutes: %d\n"
ADD R0, PC ; char *
BLX _printf
LDR R1, [SP,#0x38+var_34]
MOV R0, 0xF25 ; "Seconds: %d\n"
ADD R0, PC ; char *
BLX _printf
ADD SP, SP, #0x30
POP {R7,PC}

...

00000000 tm struc ; (sizeof=0x2C, standard type)


00000000 tm_sec DCD ?
00000004 tm_min DCD ?
00000008 tm_hour DCD ?
0000000C tm_mday DCD ?
00000010 tm_mon DCD ?
00000014 tm_year DCD ?
00000018 tm_wday DCD ?
0000001C tm_yday DCD ?
00000020 tm_isdst DCD ?
00000024 tm_gmtoff DCD ?
00000028 tm_zone DCD ? ; offset
0000002C tm ends

21.3.3. MIPS

21.11: GCC 4.4.5 (IDA)


1 main:
2
3 ; IDA , :
4
5 var_40 = 0x40
6 var_38 = 0x38
7 seconds = 0x34

371
21. 21.
8 minutes = 0x30
9 hour = 0x2C
10 day = 0x28
11 month = 0x24
12 year = 0x20
13 var_4 = 4
14
15 lui $gp, (__gnu_local_gp >> 16)
16 addiu $sp, 0x50
17 la $gp, (__gnu_local_gp & 0xFFFF)
18 sw $ra, 0x50+var_4($sp)
19 sw $gp, 0x50+var_40($sp)
20 lw $t9, (time & 0xFFFF)($gp)
21 or $at, $zero ; load delay slot, NOP
22 jalr $t9
23 move $a0, $zero ; branch delay slot, NOP
24 lw $gp, 0x50+var_40($sp)
25 addiu $a0, $sp, 0x50+var_38
26 lw $t9, (localtime_r & 0xFFFF)($gp)
27 addiu $a1, $sp, 0x50+seconds
28 jalr $t9
29 sw $v0, 0x50+var_38($sp) ; branch delay slot
30 lw $gp, 0x50+var_40($sp)
31 lw $a1, 0x50+year($sp)
32 lw $t9, (printf & 0xFFFF)($gp)
33 la $a0, $LC0 # "Year: %d\n"
34 jalr $t9
35 addiu $a1, 1900 ; branch delay slot
36 lw $gp, 0x50+var_40($sp)
37 lw $a1, 0x50+month($sp)
38 lw $t9, (printf & 0xFFFF)($gp)
39 lui $a0, ($LC1 >> 16) # "Month: %d\n"
40 jalr $t9
41 la $a0, ($LC1 & 0xFFFF) # "Month: %d\n" ; branch delay slot
42 lw $gp, 0x50+var_40($sp)
43 lw $a1, 0x50+day($sp)
44 lw $t9, (printf & 0xFFFF)($gp)
45 lui $a0, ($LC2 >> 16) # "Day: %d\n"
46 jalr $t9
47 la $a0, ($LC2 & 0xFFFF) # "Day: %d\n" ; branch delay slot
48 lw $gp, 0x50+var_40($sp)
49 lw $a1, 0x50+hour($sp)
50 lw $t9, (printf & 0xFFFF)($gp)
51 lui $a0, ($LC3 >> 16) # "Hour: %d\n"
52 jalr $t9
53 la $a0, ($LC3 & 0xFFFF) # "Hour: %d\n" ; branch delay slot
54 lw $gp, 0x50+var_40($sp)
55 lw $a1, 0x50+minutes($sp)
56 lw $t9, (printf & 0xFFFF)($gp)
57 lui $a0, ($LC4 >> 16) # "Minutes: %d\n"
58 jalr $t9
59 la $a0, ($LC4 & 0xFFFF) # "Minutes: %d\n" ; branch delay slot
60 lw $gp, 0x50+var_40($sp)
61 lw $a1, 0x50+seconds($sp)
62 lw $t9, (printf & 0xFFFF)($gp)
63 lui $a0, ($LC5 >> 16) # "Seconds: %d\n"
64 jalr $t9
65 la $a0, ($LC5 & 0xFFFF) # "Seconds: %d\n" ; branch delay slot
66 lw $ra, 0x50+var_4($sp)
67 or $at, $zero ; load delay slot, NOP
68 jr $ra
69 addiu $sp, 0x50
70
71 $LC0: .ascii "Year: %d\n"<0>
72 $LC1: .ascii "Month: %d\n"<0>
73 $LC2: .ascii "Day: %d\n"<0>
74 $LC3: .ascii "Hour: %d\n"<0>
75 $LC4: .ascii "Minutes: %d\n"<0>
76 $LC5: .ascii "Seconds: %d\n"<0>

372
21. 21.
, branch delay slot- . , 35 addiu $a1, 1900,
1900 . JALR 34, -
.

21.3.4.

, ,
, tm : .21.8.
#include <stdio.h>
#include <time.h>

void main()
{
int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday, tm_isdst;
time_t unix_time;

unix_time=time(NULL);

localtime_r (&unix_time, &tm_sec);

printf ("Year: %d\n", tm_year+1900);


printf ("Month: %d\n", tm_mon);
printf ("Day: %d\n", tm_mday);
printf ("Hour: %d\n", tm_hour);
printf ("Minutes: %d\n", tm_min);
printf ("Seconds: %d\n", tm_sec);
};

N.B. localtime_r tm_sec, .. .


, :

21.12: GCC 4.7.3


GCC_tm2.c: In function 'main':
GCC_tm2.c:11:5: warning: passing argument 2 of 'localtime_r' from incompatible pointer type [enabled
by default]
In file included from GCC_tm2.c:2:0:
/usr/include/time.h:59:12: note: expected 'struct tm *' but argument is of type 'int *'

, :

21.13: GCC 4.7.3


main proc near

var_30 = dword ptr 30h


var_2C = dword ptr 2Ch
unix_time = dword ptr 1Ch
tm_sec = dword ptr 18h
tm_min = dword ptr 14h
tm_hour = dword ptr 10h
tm_mday = dword ptr 0Ch
tm_mon = dword ptr 8
tm_year = dword ptr 4

push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 30h
call __main
mov [esp+30h+var_30], 0 ; arg 0
call time
mov [esp+30h+unix_time], eax
lea eax, [esp+30h+tm_sec]
mov [esp+30h+var_2C], eax
lea eax, [esp+30h+unix_time]
mov [esp+30h+var_30], eax
call localtime_r

373
21. 21.
mov eax, [esp+30h+tm_year]
add eax, 1900
mov [esp+30h+var_2C], eax
mov [esp+30h+var_30], offset aYearD ; "Year: %d\n"
call printf
mov eax, [esp+30h+tm_mon]
mov [esp+30h+var_2C], eax
mov [esp+30h+var_30], offset aMonthD ; "Month: %d\n"
call printf
mov eax, [esp+30h+tm_mday]
mov [esp+30h+var_2C], eax
mov [esp+30h+var_30], offset aDayD ; "Day: %d\n"
call printf
mov eax, [esp+30h+tm_hour]
mov [esp+30h+var_2C], eax
mov [esp+30h+var_30], offset aHourD ; "Hour: %d\n"
call printf
mov eax, [esp+30h+tm_min]
mov [esp+30h+var_2C], eax
mov [esp+30h+var_30], offset aMinutesD ; "Minutes: %d\n"
call printf
mov eax, [esp+30h+tm_sec]
mov [esp+30h+var_2C], eax
mov [esp+30h+var_30], offset aSecondsD ; "Seconds: %d\n"
call printf
leave
retn
main endp

, ,
.
. , . , -
, . ,
.
, - , tm_year, tm_mon, tm_mday, tm_hour,
tm_min, tm_sec, . , -
localtime_r().
, int. ,
16 (WORD), SYSTEMTIME GetSystemTime()
( 32- ). :
(21.4 (. 377)).
, , . , -
, . , -,
( 1972) [Rit93].
: , .

21.3.5. 32-

#include <stdio.h>
#include <time.h>

void main()
{
struct tm t;
time_t unix_time;
int i;

unix_time=time(NULL);

localtime_r (&unix_time, &t);

for (i=0; i<9; i++)


{
int tmp=((int*)&t)[i];

374
21. 21.
printf ("0x%08X (%d)\n", tmp, tmp);
};
};

(cast) int-. ! 23:51:45 26-July-


2014.
0x0000002D (45)
0x00000033 (51)
0x00000017 (23)
0x0000001A (26)
0x00000006 (6)
0x00000072 (114)
0x00000006 (6)
0x000000CE (206)
0x00000001 (1)

, : 21.8 (. 369).
:

21.14: GCC 4.8.1


main proc near
push ebp
mov ebp, esp
push esi
push ebx
and esp, 0FFFFFFF0h
sub esp, 40h
mov dword ptr [esp], 0 ; timer
lea ebx, [esp+14h]
call _time
lea esi, [esp+38h]
mov [esp+4], ebx ; tp
mov [esp+10h], eax
lea eax, [esp+10h]
mov [esp], eax ; timer
call _localtime_r
nop
lea esi, [esi+0] ; NOP
loc_80483D8:
; EBX , ESI - .
mov eax, [ebx] ; 32-
add ebx, 4 ;
mov dword ptr [esp+4], offset a0x08xD ; "0x%08X (%d)\n"
mov dword ptr [esp], 1
mov [esp+0Ch], eax ; printf()
mov [esp+8], eax ; printf()
call ___printf_chk
cmp ebx, esi ; ?
jnz short loc_80483D8 ; -
lea esp, [ebp8]
pop ebx
pop esi
pop ebp
retn
main endp

: , .
.
, , .

, ( 1)
.

375
21. 21.
21.3.6.

. (cast) :
#include <stdio.h>
#include <time.h>

void main()
{
struct tm t;
time_t unix_time;
int i, j;

unix_time=time(NULL);

localtime_r (&unix_time, &t);

for (i=0; i<9; i++)


{
for (j=0; j<4; j++)
printf ("0x%02X ", ((unsigned char*)&t)[i*4+j]);
printf ("\n");
};
};

0x2D 0x00 0x00 0x00


0x33 0x00 0x00 0x00
0x17 0x00 0x00 0x00
0x1A 0x00 0x00 0x00
0x06 0x00 0x00 0x00
0x72 0x00 0x00 0x00
0x06 0x00 0x00 0x00
0xCE 0x00 0x00 0x00
0x01 0x00 0x00 0x00

23:51:45 26-July-2014 5 . ,
(21.3.5 (. 375)), , , little-endian (31 (. 473)).

21.15: GCC 4.8.1


main proc near
push ebp
mov ebp, esp
push edi
push esi
push ebx
and esp, 0FFFFFFF0h
sub esp, 40h
mov dword ptr [esp], 0 ; timer
lea esi, [esp+14h]
call _time
lea edi, [esp+38h] ; struct end
mov [esp+4], esi ; tp
mov [esp+10h], eax
lea eax, [esp+10h]
mov [esp], eax ; timer
call _localtime_r
lea esi, [esi+0] ; NOP
; ESI . EDI .
loc_8048408:
xor ebx, ebx ; j=0

loc_804840A:
movzx eax, byte ptr [esi+ebx] ;
add ebx, 1 ; j=j+1
mov dword ptr [esp+4], offset a0x02x ; "0x%02X "
mov dword ptr [esp], 1
mov [esp+8], eax ; printf()
5 . .

376
21. 21.
call ___printf_chk
cmp ebx, 4
jnz short loc_804840A
; (CR)
mov dword ptr [esp], 0Ah ; c
add esi, 4
call _putchar
cmp esi, edi ; ?
jnz short loc_8048408 ; j=0
lea esp, [ebp0Ch]
pop ebx
pop esi
pop edi
pop ebp
retn
main endp

21.4.
, 6 .
:
#include <stdio.h>

struct s
{
char a;
int b;
char c;
int d;
};

void f(struct s s)
{
printf ("a=%d; b=%d; c=%d; d=%d\n", s.a, s.b, s.c, s.d);
};

int main()
{
struct s tmp;
tmp.a=1;
tmp.b=2;
tmp.c=3;
tmp.d=4;
f(tmp);
};

, char ( ) int ( 4 ).

21.4.1. x86

21.16: MSVC 2012 /GS- /Ob0


1 _tmp$ = 16
2 _main PROC
3 push ebp
4 mov ebp, esp
5 sub esp, 16
6 mov BYTE PTR _tmp$[ebp], 1 ; a
7 mov DWORD PTR _tmp$[ebp+4], 2 ; b
8 mov BYTE PTR _tmp$[ebp+8], 3 ; c
9 mov DWORD PTR _tmp$[ebp+12], 4 ; d
6 . : Wikipedia:

377
21. 21.
10 sub esp, 16 ;
11 mov eax, esp
12 mov ecx, DWORD PTR _tmp$[ebp] ;
13 mov DWORD PTR [eax], ecx
14 mov edx, DWORD PTR _tmp$[ebp+4]
15 mov DWORD PTR [eax+4], edx
16 mov ecx, DWORD PTR _tmp$[ebp+8]
17 mov DWORD PTR [eax+8], ecx
18 mov edx, DWORD PTR _tmp$[ebp+12]
19 mov DWORD PTR [eax+12], edx
20 call _f
21 add esp, 16
22 xor eax, eax
23 mov esp, ebp
24 pop ebp
25 ret 0
26 _main ENDP
27
28 _s$ = 8 ; size = 16
29 ?f@@YAXUs@@@Z PROC ; f
30 push ebp
31 mov ebp, esp
32 mov eax, DWORD PTR _s$[ebp+12]
33 push eax
34 movsx ecx, BYTE PTR _s$[ebp+8]
35 push ecx
36 mov edx, DWORD PTR _s$[ebp+4]
37 push edx
38 movsx eax, BYTE PTR _s$[ebp]
39 push eax
40 push OFFSET $SG3842
41 call _printf
42 add esp, 20
43 pop ebp
44 ret 0
45 ?f@@YAXUs@@@Z ENDP ; f
46 _TEXT ENDS

, , , ,
( 10, 4 , , 12 19),
( ). , ,
f() . , main() .
/++, , .
4- . char
4 int. ?
.
.
(/Zp1) (/Zp[n] pack structures on n-byte boundary).

21.17: MSVC 2012 /GS- /Zp1


1 _main PROC
2 push ebp
3 mov ebp, esp
4 sub esp, 12
5 mov BYTE PTR _tmp$[ebp], 1 ; a
6 mov DWORD PTR _tmp$[ebp+1], 2 ; b
7 mov BYTE PTR _tmp$[ebp+5], 3 ; c
8 mov DWORD PTR _tmp$[ebp+6], 4 ; d
9 sub esp, 12 ;
10 mov eax, esp
11 mov ecx, DWORD PTR _tmp$[ebp] ; 10
12 mov DWORD PTR [eax], ecx
13 mov edx, DWORD PTR _tmp$[ebp+4]
14 mov DWORD PTR [eax+4], edx
15 mov cx, WORD PTR _tmp$[ebp+8]
16 mov WORD PTR [eax+8], cx
17 call _f

378
21. 21.
18 add esp, 12
19 xor eax, eax
20 mov esp, ebp
21 pop ebp
22 ret 0
23 _main ENDP
24
25 _TEXT SEGMENT
26 _s$ = 8 ; size = 10
27 ?f@@YAXUs@@@Z PROC ; f
28 push ebp
29 mov ebp, esp
30 mov eax, DWORD PTR _s$[ebp+6]
31 push eax
32 movsx ecx, BYTE PTR _s$[ebp+5]
33 push ecx
34 mov edx, DWORD PTR _s$[ebp+1]
35 push edx
36 movsx eax, BYTE PTR _s$[ebp]
37 push eax
38 push OFFSET $SG3842
39 call _printf
40 add esp, 20
41 pop ebp
42 ret 0
43 ?f@@YAXUs@@@Z ENDP ; f

10 char . ? .
, .
main(). , 10 , MOV. 4?
, 10 3 MOV, 32-
4 MOV. , MOV
memcpy(), , ,
memcpy() , : 43.1.5 (. 527).
, ,
.
MSVC /Zp, , ,
#pragma pack, . MSVC7 GCC8 .
SYSTEMTIME, 16- .
?
WinNT.h :

21.18: WinNT.h
#include "pshpack1.h"

21.19: WinNT.h
#include "pshpack4.h" // 4 byte packing is the default

PshPack1.h :

21.20: PshPack1.h
#if ! (defined(lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(push,1)
#else
#pragma pack(1)
#endif
#else
7 MSDN: Working with Packing Structures
8 Structure-Packing Pragmas

379
21. 21.
#pragma pack(1)
#endif
#endif /* ! (defined(lint) || defined(RC_INVOKED)) */

, , #pragma pack .

380
21. 21.
OllyDbg +

OllyDbg , (4 ) :

. 21.3: OllyDbg: printf()

. , (0x30, 0x37, 0x01)


(a) (c) ? 21.16 (. 377), , char,
, , 1 3 ( 6 8). 32-
! , , .
printf(), MOVSX,
: .21.16 ( 34 38).
, MOVSX ( ), char MSVC
GCC. unsigned char uint8_t, MOVZX.

381
21. 21.
OllyDbg + 1

: 4 10

. 21.4: OllyDbg: printf()

21.4.2. ARM

Keil 6/2013 ( Thumb)

21.21: Keil 6/2013 ( Thumb)


.text:0000003E exit ; CODE XREF: f+16
.text:0000003E 05 B0 ADD SP, SP, #0x14
.text:00000040 00 BD POP {PC}

.text:00000280 f
.text:00000280
.text:00000280 var_18 = 0x18
.text:00000280 a = 0x14
.text:00000280 b = 0x10
.text:00000280 c = 0xC
.text:00000280 d = 8
.text:00000280
.text:00000280 0F B5 PUSH {R0R3,LR}
.text:00000282 81 B0 SUB SP, SP, #4
.text:00000284 04 98 LDR R0, [SP,#16] ; d
.text:00000286 02 9A LDR R2, [SP,#8] ; b
.text:00000288 00 90 STR R0, [SP]
.text:0000028A 68 46 MOV R0, SP
.text:0000028C 03 7B LDRB R3, [R0,#12] ; c
.text:0000028E 01 79 LDRB R1, [R0,#4] ; a
.text:00000290 59 A0 ADR R0, aADBDCDDD ; "a=%d; b=%d; c=%d; d=%d\n"
.text:00000292 05 F0 AD FF BL __2printf
.text:00000296 D2 E6 B exit

, , , ARM 4
, R0-R3.
LDRB 32- .
MOVSX x86. a c .
, , ! ,
, , , , (,
5 (5 4 = 0x14)). , ( ). -
, , , , . Keil
, , - . 4 , 2.

382
21. 21.
ARM + Xcode 4.6.3 (LLVM) ( Thumb-2)

21.22: Xcode 4.6.3 (LLVM) ( Thumb-2)


var_C = 0xC

PUSH {R7,LR}
MOV R7, SP
SUB SP, SP, #4
MOV R9, R1 ; b
MOV R1, R0 ; a
MOVW R0, #0xF10 ; "a=%d; b=%d; c=%d; d=%d\n"
SXTB R1, R1 ; prepare a
MOVT.W R0, #0
STR R3, [SP,#0xC+var_C] ; place d to stack for printf()
ADD R0, PC ; formatstring
SXTB R3, R2 ; prepare c
MOV R2, R9 ; b
BLX _printf
ADD SP, SP, #4
POP {R7,PC}

SXTB (Signed Extend Byte) MOVSX x86. .

21.4.3. MIPS

21.23: GCC 4.4.5 (IDA)


1 f:
2
3 var_18 = 0x18
4 var_10 = 0x10
5 var_4 = 4
6 arg_0 = 0
7 arg_4 = 4
8 arg_8 = 8
9 arg_C = 0xC
10
11 ; $a0=s.a
12 ; $a1=s.b
13 ; $a2=s.c
14 ; $a3=s.d
15 lui $gp, (__gnu_local_gp >> 16)
16 addiu $sp, 0x28
17 la $gp, (__gnu_local_gp & 0xFFFF)
18 sw $ra, 0x28+var_4($sp)
19 sw $gp, 0x28+var_10($sp)
20 ; prepare byte from 32bit bigendian integer:
21 sra $t0, $a0, 24
22 move $v1, $a1
23 ; prepare byte from 32bit bigendian integer:
24 sra $v0, $a2, 24
25 lw $t9, (printf & 0xFFFF)($gp)
26 sw $a0, 0x28+arg_0($sp)
27 lui $a0, ($LC0 >> 16) # "a=%d; b=%d; c=%d; d=%d\n"
28 sw $a3, 0x28+var_18($sp)
29 sw $a1, 0x28+arg_4($sp)
30 sw $a2, 0x28+arg_8($sp)
31 sw $a3, 0x28+arg_C($sp)
32 la $a0, ($LC0 & 0xFFFF) # "a=%d; b=%d; c=%d; d=%d\n"
33 move $a1, $t0
34 move $a2, $v1
35 jalr $t9
36 move $a3, $v0 ; branch delay slot
37 lw $ra, 0x28+var_4($sp)
38 or $at, $zero ; load delay slot, NOP
39 jr $ra
40 addiu $sp, 0x28 ; branch delay slot
41

383
21. 21.
42 $LC0: .ascii "a=%d; b=%d; c=%d; d=%d\n"<0>

$A0..$A3 $A1..$A4 printf().


SRA (Shift Word Right Arithmetic), char. ? , MIPS
big-endian 31 (. 473), Debian Linux , big-endian.
32- , 31..24. char
32- , 24 . char ,
.

21.4.4. -

( )
. , f() :
void f(char a, int b, char c, int d)
{
printf ("a=%d; b=%d; c=%d; d=%d\n", a, b, c, d);
};

21.5.
, , ?
#include <stdio.h>

struct inner_struct
{
int a;
int b;
};

struct outer_struct
{
char a;
int b;
struct inner_struct c;
char d;
int e;
};

void f(struct outer_struct s)


{
printf ("a=%d; b=%d; c.a=%d; c.b=%d; d=%d; e=%d\n",
s.a, s.b, s.c.a, s.c.b, s.d, s.e);
};

int main()
{
struct outer_struct s;
s.a=1;
s.b=2;
s.c.a=100;
s.c.b=101;
s.d=3;
s.e=4;
f(s);
};

, inner_struct a,b d,e outer_struct.


(MSVC 2010):

21.24: MSVC 2010 /Ob0


$SG2802 DB 'a=%d; b=%d; c.a=%d; c.b=%d; d=%d; e=%d', 0aH, 00H

384
21. 21.

_TEXT SEGMENT
_s$ = 8
_f PROC
mov eax, DWORD PTR _s$[esp+16]
movsx ecx, BYTE PTR _s$[esp+12]
mov edx, DWORD PTR _s$[esp+8]
push eax
mov eax, DWORD PTR _s$[esp+8]
push ecx
mov ecx, DWORD PTR _s$[esp+8]
push edx
movsx edx, BYTE PTR _s$[esp+8]
push eax
push ecx
push edx
push OFFSET $SG2802 ; 'a=%d; b=%d; c.a=%d; c.b=%d; d=%d; e=%d'
call _printf
add esp, 28
ret 0
_f ENDP

_s$ = 24
_main PROC
sub esp, 24
push ebx
push esi
push edi
mov ecx, 2
sub esp, 24
mov eax, esp
mov BYTE PTR _s$[esp+60], 1
mov ebx, DWORD PTR _s$[esp+60]
mov DWORD PTR [eax], ebx
mov DWORD PTR [eax+4], ecx
lea edx, DWORD PTR [ecx+98]
lea esi, DWORD PTR [ecx+99]
lea edi, DWORD PTR [ecx+2]
mov DWORD PTR [eax+8], edx
mov BYTE PTR _s$[esp+76], 3
mov ecx, DWORD PTR _s$[esp+76]
mov DWORD PTR [eax+12], esi
mov DWORD PTR [eax+16], ecx
mov DWORD PTR [eax+20], edi
call _f
add esp, 24
pop edi
pop esi
xor eax, eax
pop ebx
add esp, 24
ret 0
_main ENDP

, , ,
- ! , , , -
, .
, struct inner_struct c; struct inner_struct *c; ( -
), .

385
21. 21.
21.5.1. OllyDbg

OllyDbg outer_struct :

. 21.5: OllyDbg: printf()

:
(outer_struct.a) () 1 + 3 ;
(outer_struct.b) (32- ) 2;
(inner_struct.a) (32- ) 0x64 (100);
(inner_struct.b) (32- ) 0x65 (101);
(outer_struct.d) () 3 + 3 ;
(outer_struct.e) (32- ) 4.

21.6.

21.6.1. CPUID

/++ , .
. , bool . , ,
.
CPUID9 . ,
.
EAX 1, CPUID EAX -
:
3:0 (4 ) Stepping
7:4 (4 ) Model
11:8 (4 ) Family
13:12 (2 ) Processor Type
19:16 (4 ) Extended Model
27:20 (8 ) Extended Family
MSVC 2010 CPUID, GCC 4.4.1 . GCC ,
10 .
#include <stdio.h>

#ifdef __GNUC__
9 wikipedia
10 GCC

386
21. 21.
static inline void cpuid(int code, int *a, int *b, int *c, int *d) {
asm volatile("cpuid":"=a"(*a),"=b"(*b),"=c"(*c),"=d"(*d):"a"(code));
}
#endif

#ifdef _MSC_VER
#include <intrin.h>
#endif

struct CPUID_1_EAX
{
unsigned int stepping:4;
unsigned int model:4;
unsigned int family_id:4;
unsigned int processor_type:2;
unsigned int reserved1:2;
unsigned int extended_model_id:4;
unsigned int extended_family_id:8;
unsigned int reserved2:4;
};

int main()
{
struct CPUID_1_EAX *tmp;
int b[4];

#ifdef _MSC_VER
__cpuid(b,1);
#endif

#ifdef __GNUC__
cpuid (1, &b[0], &b[1], &b[2], &b[3]);
#endif

tmp=(struct CPUID_1_EAX *)&b[0];

printf ("stepping=%d\n", tmp>stepping);


printf ("model=%d\n", tmp>model);
printf ("family_id=%d\n", tmp>family_id);
printf ("processor_type=%d\n", tmp>processor_type);
printf ("extended_model_id=%d\n", tmp>extended_model_id);
printf ("extended_family_id=%d\n", tmp>extended_family_id);

return 0;
};

CPUID EAX/ EBX/ ECX/ EDX, b[]. ,


CPUID_1_EAX, EAX b[].
, 32- int . .

MSVC

MSVC 2008 /Ox:


21.25: MSVC 2008
_b$ = 16 ; size = 16
_main PROC
sub esp, 16
push ebx

xor ecx, ecx


mov eax, 1
cpuid
push esi
lea esi, DWORD PTR _b$[esp+24]
mov DWORD PTR [esi], eax
mov DWORD PTR [esi+4], ebx
mov DWORD PTR [esi+8], ecx

387
21. 21.
mov DWORD PTR [esi+12], edx

mov esi, DWORD PTR _b$[esp+24]


mov eax, esi
and eax, 15
push eax
push OFFSET $SG15435 ; 'stepping=%d', 0aH, 00H
call _printf

mov ecx, esi


shr ecx, 4
and ecx, 15
push ecx
push OFFSET $SG15436 ; 'model=%d', 0aH, 00H
call _printf

mov edx, esi


shr edx, 8
and edx, 15
push edx
push OFFSET $SG15437 ; 'family_id=%d', 0aH, 00H
call _printf

mov eax, esi


shr eax, 12
and eax, 3
push eax
push OFFSET $SG15438 ; 'processor_type=%d', 0aH, 00H
call _printf

mov ecx, esi


shr ecx, 16
and ecx, 15
push ecx
push OFFSET $SG15439 ; 'extended_model_id=%d', 0aH, 00H
call _printf

shr esi, 20
and esi, 255
push esi
push OFFSET $SG15440 ; 'extended_family_id=%d', 0aH, 00H
call _printf
add esp, 48
pop esi

xor eax, eax


pop ebx

add esp, 16
ret 0
_main ENDP

SHR EAX , , ,
.
AND , , ,
EAX, .

388
21. 21.
MSVC + OllyDbg

OllyDbg , EAX/EBX/ECX/EDX CPUID:

. 21.6: OllyDbg: CPUID

EAX 0x000206A7 ( CPU Intel Xeon E3-1220).


00000000000000100000011010100111.
:

reserved2 0000 0
extended_family_id 00000000 0
extended_model_id 0010 2
reserved1 00 0
processor_id 00 0
family_id 0110 6
model 1010 10
stepping 0111 7

. 21.7: OllyDbg:

GCC

GCC 4.4.1 -O3.

21.26: GCC 4.4.1


main proc near ; DATA XREF: _start+17
push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
push esi

389
21. 21.
mov esi, 1
push ebx
mov eax, esi
sub esp, 18h
cpuid
mov esi, eax
and eax, 0Fh
mov [esp+8], eax
mov dword ptr [esp+4], offset aSteppingD ; "stepping=%d\n"
mov dword ptr [esp], 1
call ___printf_chk
mov eax, esi
shr eax, 4
and eax, 0Fh
mov [esp+8], eax
mov dword ptr [esp+4], offset aModelD ; "model=%d\n"
mov dword ptr [esp], 1
call ___printf_chk
mov eax, esi
shr eax, 8
and eax, 0Fh
mov [esp+8], eax
mov dword ptr [esp+4], offset aFamily_idD ; "family_id=%d\n"
mov dword ptr [esp], 1
call ___printf_chk
mov eax, esi
shr eax, 0Ch
and eax, 3
mov [esp+8], eax
mov dword ptr [esp+4], offset aProcessor_type ; "processor_type=%d\n"
mov dword ptr [esp], 1
call ___printf_chk
mov eax, esi
shr eax, 10h
shr esi, 14h
and eax, 0Fh
and esi, 0FFh
mov [esp+8], eax
mov dword ptr [esp+4], offset aExtended_model ; "extended_model_id=%d\n"
mov dword ptr [esp], 1
call ___printf_chk
mov [esp+8], esi
mov dword ptr [esp+4], offset unk_80486D0
mov dword ptr [esp], 1
call ___printf_chk
add esp, 18h
xor eax, eax
pop ebx
pop esi
mov esp, ebp
pop ebp
retn
main endp

, . , GCC -
extended_model_id extended_family_id ,
printf().

21.6.2. oat

FPU (17 (. 217)), oat double , .


, ? oat.

31 30 23 22 0

( S )

390
21. 21.

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <memory.h>

struct float_as_struct
{
unsigned int fraction : 23; //
unsigned int exponent : 8; // + 0x3FF
unsigned int sign : 1; //
};

float f(float )
{
float f=;
struct float_as_struct t;

assert (sizeof (struct float_as_struct) == sizeof (float));

memcpy (&t, &f, sizeof (float));

t.sign=1; //
t.exponent=t.exponent+2; // d 2n (n 2)

memcpy (&f, &t, sizeof (float));

return f;
};

int main()
{
printf ("%f\n", f(1.234));
};

float_as_struct oat, 4 32 .
, ,
22 , 4.
MSVC 2008 :
21.27: MSVC 2008
_t$ = 8 ; size = 4
_f$ = 4 ; size = 4
__in$ = 8 ; size = 4
?f@@YAMM@Z PROC ; f
push ebp
mov ebp, esp
sub esp, 8

fld DWORD PTR __in$[ebp]


fstp DWORD PTR _f$[ebp]

push 4
lea eax, DWORD PTR _f$[ebp]
push eax
lea ecx, DWORD PTR _t$[ebp]
push ecx
call _memcpy
add esp, 12

mov edx, DWORD PTR _t$[ebp]


or edx, 2147483648 ; 80000000H
mov DWORD PTR _t$[ebp], edx

mov eax, DWORD PTR _t$[ebp]


shr eax, 23 ; 00000017H
and eax, 255 ; 000000ffH
add eax, 2 ; 2
and eax, 255 ; 000000ffH

391
21. 21.
shl eax, 23 ; 00000017H 30:23
mov ecx, DWORD PTR _t$[ebp]
and ecx, 2139095041 ; 807fffffH

;
or ecx, eax
mov DWORD PTR _t$[ebp], ecx

push 4
lea edx, DWORD PTR _t$[ebp]
push edx
lea eax, DWORD PTR _f$[ebp]
push eax
call _memcpy
add esp, 12

fld DWORD PTR _f$[ebp]

mov esp, ebp


pop ebp
ret 0
?f@@YAMM@Z ENDP ; f

. /Ox memcpy(),
f. .
GCC 4.4.1 -O3?

21.28: GCC 4.4.1


; f(float)
public _Z1ff
_Z1ff proc near

var_4 = dword ptr 4


arg_0 = dword ptr 8

push ebp
mov ebp, esp
sub esp, 4
mov eax, [ebp+arg_0]
or eax, 80000000h ;
mov edx, eax
and eax, 807FFFFFh ; EAX
shr edx, 23 ;
add edx, 2 ; 2
movzx edx, dl ; 7:0 EAX 0
shl edx, 23 ;
or eax, edx ;
mov [ebp+var_4], eax
fld [ebp+var_4]
leave
retn
_Z1ff endp

public main
main proc near
push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 10h
fld ds:dword_8048614 ; 4.936
fstp qword ptr [esp+8]
mov dword ptr [esp+4], offset asc_8048610 ; "%f\n"
mov dword ptr [esp], 1
call ___printf_chk
xor eax, eax
leave
retn
main endp

392
21. 21.
, f() . , , , -
, GCC f(1.234)
printf()!

21.7.

21.7.1. #1

Linux x86 (beginners.re)11


Linux MIPS (beginners.re)12
Linux x86 Linux MIPS - . ?
: G.1.14 (. 990).

21.7.2. #2

- -. ,
. .

21.29: MSVC 2010


$SG2802 DB '%f', 0aH, 00H
$SG2803 DB '%c, %d', 0aH, 00H
$SG2805 DB 'error #2', 0aH, 00H
$SG2807 DB 'error #1', 0aH, 00H

__real@405ec00000000000 DQ 0405ec00000000000r ; 123


__real@407bc00000000000 DQ 0407bc00000000000r ; 444

_s$ = 8
_f PROC
push esi
mov esi, DWORD PTR _s$[esp]
cmp DWORD PTR [esi], 1000
jle SHORT $LN4@f
cmp DWORD PTR [esi+4], 10
jbe SHORT $LN3@f
fld DWORD PTR [esi+8]
sub esp, 8
fmul QWORD PTR __real@407bc00000000000
fld QWORD PTR [esi+16]
fmul QWORD PTR __real@405ec00000000000
faddp ST(1), ST(0)
fstp QWORD PTR [esp]
push OFFSET $SG2802 ; '%f'
call _printf
movzx eax, BYTE PTR [esi+25]
movsx ecx, BYTE PTR [esi+24]
push eax
push ecx
push OFFSET $SG2803 ; '%c, %d'
call _printf
add esp, 24
pop esi
ret 0
$LN3@f:
pop esi
mov DWORD PTR _s$[esp4], OFFSET $SG2805 ; 'error #2'
jmp _printf
$LN4@f:
pop esi
mov DWORD PTR _s$[esp4], OFFSET $SG2807 ; 'error #1'
jmp _printf
_f ENDP

11 GCC 4.8.1 -O3


12 GCC 4.4.5 -O3

393
21. 21.
21.30: Keil 6/2013 ( ARM)
f PROC
PUSH {r4r6,lr}
MOV r4,r0
LDR r0,[r0,#0]
CMP r0,#0x3e8
ADRLE r0,|L0.140|
BLE |L0.132|
LDR r0,[r4,#4]
CMP r0,#0xa
ADRLS r0,|L0.152|
BLS |L0.132|
ADD r0,r4,#0x10
LDM r0,{r0,r1}
LDR r3,|L0.164|
MOV r2,#0
BL __aeabi_dmul
MOV r5,r0
MOV r6,r1
LDR r0,[r4,#8]
LDR r1,|L0.168|
BL __aeabi_fmul
BL __aeabi_f2d
MOV r2,r5
MOV r3,r6
BL __aeabi_dadd
MOV r2,r0
MOV r3,r1
ADR r0,|L0.172|
BL __2printf
LDRB r2,[r4,#0x19]
LDRB r1,[r4,#0x18]
POP {r4r6,lr}
ADR r0,|L0.176|
B __2printf
|L0.132|
POP {r4r6,lr}
B __2printf
ENDP

|L0.140|
DCB "error #1\n",0
DCB 0
DCB 0
|L0.152|
DCB "error #2\n",0
DCB 0
DCB 0
|L0.164|
DCD 0x405ec000
|L0.168|
DCD 0x43de0000
|L0.172|
DCB "%f\n",0
|L0.176|
DCB "%c, %d\n",0

21.31: Keil 6/2013 ( Thumb)


f PROC
PUSH {r4r6,lr}
MOV r4,r0
LDR r0,[r0,#0]
CMP r0,#0x3e8
ADRLE r0,|L0.140|
BLE |L0.132|
LDR r0,[r4,#4]
CMP r0,#0xa
ADRLS r0,|L0.152|
BLS |L0.132|

394
21. 21.
ADD r0,r4,#0x10
LDM r0,{r0,r1}
LDR r3,|L0.164|
MOV r2,#0
BL __aeabi_dmul
MOV r5,r0
MOV r6,r1
LDR r0,[r4,#8]
LDR r1,|L0.168|
BL __aeabi_fmul
BL __aeabi_f2d
MOV r2,r5
MOV r3,r6
BL __aeabi_dadd
MOV r2,r0
MOV r3,r1
ADR r0,|L0.172|
BL __2printf
LDRB r2,[r4,#0x19]
LDRB r1,[r4,#0x18]
POP {r4r6,lr}
ADR r0,|L0.176|
B __2printf
|L0.132|
POP {r4r6,lr}
B __2printf
ENDP

|L0.140|
DCB "error #1\n",0
DCB 0
DCB 0
|L0.152|
DCB "error #2\n",0
DCB 0
DCB 0
|L0.164|
DCD 0x405ec000
|L0.168|
DCD 0x43de0000
|L0.172|
DCB "%f\n",0
|L0.176|
DCB "%c, %d\n",0

21.32: GCC 4.9 (ARM64)


f:
stp x29, x30, [sp, 32]!
add x29, sp, 0
ldr w1, [x0]
str x19, [sp,16]
cmp w1, 1000
ble .L2
ldr w1, [x0,4]
cmp w1, 10
bls .L3
ldr s1, [x0,8]
mov x19, x0
ldr s0, .LC1
adrp x0, .LC0
ldr d2, [x19,16]
add x0, x0, :lo12:.LC0
fmul s1, s1, s0
ldr d0, .LC2
fmul d0, d2, d0
fcvt d1, s1
fadd d0, d1, d0
bl printf
ldrb w1, [x19,24]

395
21. 21.
adrp x0, .LC3
ldrb w2, [x19,25]
add x0, x0, :lo12:.LC3
ldr x19, [sp,16]
ldp x29, x30, [sp], 32
b printf
.L3:
ldr x19, [sp,16]
adrp x0, .LC4
ldp x29, x30, [sp], 32
add x0, x0, :lo12:.LC4
b puts
.L2:
ldr x19, [sp,16]
adrp x0, .LC5
ldp x29, x30, [sp], 32
add x0, x0, :lo12:.LC5
b puts
.size f, .f
.LC1:
.word 1138622464
.LC2:
.word 0
.word 1079951360
.LC0:
.string "%f\n"
.LC3:
.string "%c, %d\n"
.LC4:
.string "error #2"
.LC5:
.string "error #1"

21.33: GCC 4.4.5 (MIPS) (IDA)


f:

var_10 = 0x10
var_8 = 8
var_4 = 4

lui $gp, (__gnu_local_gp >> 16)


addiu $sp, 0x20
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x20+var_4($sp)
sw $s0, 0x20+var_8($sp)
sw $gp, 0x20+var_10($sp)
lw $v0, 0($a0)
or $at, $zero
slti $v0, 0x3E9
bnez $v0, loc_C8
move $s0, $a0
lw $v0, 4($a0)
or $at, $zero
sltiu $v0, 0xB
bnez $v0, loc_AC
lui $v0, (dword_134 >> 16)
lwc1 $f4, $LC1
lwc1 $f2, 8($a0)
lui $v0, ($LC2 >> 16)
lwc1 $f0, 0x14($a0)
mul.s $f2, $f4, $f2
lwc1 $f4, dword_134
lwc1 $f1, 0x10($a0)
lwc1 $f5, $LC2
cvt.d.s $f2, $f2
mul.d $f0, $f4, $f0
lw $t9, (printf & 0xFFFF)($gp)
lui $a0, ($LC0 >> 16) # "%f\n"
add.d $f4, $f2, $f0

396
21. 21.
mfc1 $a2, $f5
mfc1 $a3, $f4
jalr $t9
la $a0, ($LC0 & 0xFFFF) # "%f\n"
lw $gp, 0x20+var_10($sp)
lbu $a2, 0x19($s0)
lb $a1, 0x18($s0)
lui $a0, ($LC3 >> 16) # "%c, %d\n"
lw $t9, (printf & 0xFFFF)($gp)
lw $ra, 0x20+var_4($sp)
lw $s0, 0x20+var_8($sp)
la $a0, ($LC3 & 0xFFFF) # "%c, %d\n"
jr $t9
addiu $sp, 0x20
loc_AC: # CODE XREF: f+38
lui $a0, ($LC4 >> 16) # "error #2"
lw $t9, (puts & 0xFFFF)($gp)
lw $ra, 0x20+var_4($sp)
lw $s0, 0x20+var_8($sp)
la $a0, ($LC4 & 0xFFFF) # "error #2"
jr $t9
addiu $sp, 0x20
loc_C8: # CODE XREF: f+24
lui $a0, ($LC5 >> 16) # "error #1"
lw $t9, (puts & 0xFFFF)($gp)
lw $ra, 0x20+var_4($sp)
lw $s0, 0x20+var_8($sp)
la $a0, ($LC5 & 0xFFFF) # "error #1"
jr $t9
addiu $sp, 0x20

$LC0: .ascii "%f\n"<0>


$LC3: .ascii "%c, %d\n"<0>
$LC4: .ascii "error #2"<0>
$LC5: .ascii "error #1"<0>

.data # .rodata.cst4
$LC1: .word 0x43DE0000

.data # .rodata.cst8
$LC2: .word 0x405EC000
dword_134: .word 0

: G.1.14 (. 991).

397
22. (UNION) 22. (UNION)

22

(union)

union /++ ( ) -
.

22.1.
0 1,
Mersenne twister. 32- DWORD.
oat RAND_MAX (0xFFFFFFFF ) 0 1.
, . FPU.
?
: , . -
, !
( ),
01111111 .
, 0 ( ), .
1 2, .
1 , 32-
. UNIX.
, oat union /++
-. , union oat
uint32_t. , , .
, : 20 (. 356).
.
#include <stdio.h>
#include <stdint.h>
#include <time.h>

// , - PRNG

// Numerical Recipes
const uint32_t RNG_a=1664525;
const uint32_t RNG_c=1013904223;
uint32_t RNG_state; //

void my_srand(uint32_t i)
{
RNG_state=i;
};

uint32_t my_rand()
{
RNG_state=RNG_state*RNG_a+RNG_c;
return RNG_state;
1 : http://go.yurichev.com/17308

398
22. (UNION) 22. (UNION)
};

// - FPU PRNG:

union uint32_t_float
{
uint32_t i;
float f;
};

float float_rand()
{
union uint32_t_float tmp;
tmp.i=my_rand() & 0x007fffff | 0x3F800000;
return tmp.f1;
};

//

int main()
{
my_srand(time(NULL)); // PRNG

for (int i=0; i<100; i++)


printf ("%f\n", float_rand());

return 0;
};

22.1.1. x86

22.1: MSVC 2010


$SG4238 DB '%f', 0aH, 00H

__real@3ff0000000000000 DQ 03ff0000000000000r ; 1

tv130 = 4
_tmp$ = 4
?float_rand@@YAMXZ PROC
push ecx
call ?my_rand@@YAIXZ
; EAX=
and eax, 8388607 ; 007fffffH
or eax, 1065353216 ; 3f800000H
; EAX= & 0x007fffff | 0x3f800000
;
mov DWORD PTR _tmp$[esp+4], eax
; :
fld DWORD PTR _tmp$[esp+4]
; 1.0:
fsub QWORD PTR __real@3ff0000000000000
;
fstp DWORD PTR tv130[esp+4] ; \
fld DWORD PTR tv130[esp+4] ; /
pop ecx
ret 0
?float_rand@@YAMXZ ENDP

_main PROC
push esi
xor eax, eax
call _time
push eax
call ?my_srand@@YAXI@Z
add esp, 4
mov esi, 100
$LL3@main:

399
22. (UNION) 22. (UNION)
call ?float_rand@@YAMXZ
sub esp, 8
fstp QWORD PTR [esp]
push OFFSET $SG4238
call _printf
add esp, 12
dec esi
jne SHORT $LL3@main
xor eax, eax
pop esi
ret 0
_main ENDP

, ++, ++,
: 51.1.1 (. 564).
MSVC 2012, SIMD- FPU, :
27.5 (. 462).

22.1.2. MIPS

22.2: GCC 4.4.5


float_rand:

var_10 = 0x10
var_4 = 4

lui $gp, (__gnu_local_gp >> 16)


addiu $sp, 0x20
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x20+var_4($sp)
sw $gp, 0x20+var_10($sp)
; my_rand():
jal my_rand
or $at, $zero ; branch delay slot, NOP
; $v0=32-
li $v1, 0x7FFFFF
; $v1=0x7FFFFF
and $v1, $v0, $v1
; $v1= & 0x7FFFFF
lui $a0, 0x3F80
; $a0=0x3F800000
or $v1, $a0
; $v1= & 0x7FFFFF | 0x3F800000
; :
lui $v0, ($LC0 >> 16)
; 1.0 $f0:
lwc1 $f0, $LC0
; $v1 ( $f2)
; ,
mtc1 $v1, $f2
lw $ra, 0x20+var_4($sp)
; 1.0. $f0:
sub.s $f0, $f2, $f0
jr $ra
addiu $sp, 0x20 ; branch delay slot

main:

var_18 = 0x18
var_10 = 0x10
var_C = 0xC
var_8 = 8
var_4 = 4

lui $gp, (__gnu_local_gp >> 16)


addiu $sp, 0x28
la $gp, (__gnu_local_gp & 0xFFFF)

400
22. (UNION) 22. (UNION)
sw $ra, 0x28+var_4($sp)
sw $s2, 0x28+var_8($sp)
sw $s1, 0x28+var_C($sp)
sw $s0, 0x28+var_10($sp)
sw $gp, 0x28+var_18($sp)
lw $t9, (time & 0xFFFF)($gp)
or $at, $zero ; load delay slot, NOP
jalr $t9
move $a0, $zero ; branch delay slot
lui $s2, ($LC1 >> 16) # "%f\n"
move $a0, $v0
la $s2, ($LC1 & 0xFFFF) # "%f\n"
move $s0, $zero
jal my_srand
li $s1, 0x64 # 'd' ; branch delay slot

loc_104:
jal float_rand
addiu $s0, 1
lw $gp, 0x28+var_18($sp)
; float_rand() double ( printf()):
cvt.d.s $f2, $f0
lw $t9, (printf & 0xFFFF)($gp)
mfc1 $a3, $f2
mfc1 $a2, $f3
jalr $t9
move $a0, $s2
bne $s0, $s1, loc_104
move $v0, $zero
lw $ra, 0x28+var_4($sp)
lw $s2, 0x28+var_8($sp)
lw $s1, 0x28+var_C($sp)
lw $s0, 0x28+var_10($sp)
jr $ra
addiu $sp, 0x28 ; branch delay slot

$LC1: .ascii "%f\n"<0>


$LC0: .float 1.0

- LUI, . :
17.5.6 (. 228).

22.1.3. ARM ( ARM)

22.3: GCC 4.6.3 (IDA)


float_rand
STMFD SP!, {R3,LR}
BL my_rand
; R0=
FLDS S0, =1.0
; S0=1.0
BIC R3, R0, #0xFF000000
BIC R3, R3, #0x800000
ORR R3, R3, #0x3F800000
; R3= & 0x007fffff | 0x3f800000
; R3 FPU ( S15).
; ,
FMSR S15, R3
; 1.0 S0:
FSUBS S0, S15, S0
LDMFD SP!, {R3,PC}

flt_5C DCFS 1.0

main
STMFD SP!, {R4,LR}
MOV R0, #0
BL time

401
22. (UNION) 22. (UNION)
BL my_srand
MOV R4, #0x64 ; 'd'

loc_78
BL float_rand
; S0=
LDR R0, =aF ; "%f"
; float double ( printf()):
FCVTDS D7, S0
; D7 R2/R3 ( printf()):
FMRRD R2, R3, D7
BL printf
SUBS R4, R4, #1
BNE loc_78
MOV R0, R4
LDMFD SP!, {R4,PC}

aF DCB "%f",0xA,0

objdump FPU- IDA. ,


IDA binutils ? ,
.

22.4: GCC 4.6.3 (objdump)


00000038 <float_rand>:
38: e92d4008 push {r3, lr}
3c: ebfffffe bl 10 <my_rand>
40: ed9f0a05 vldr s0, [pc, #20] ; 5c <float_rand+0x24>
44: e3c034ff bic r3, r0, #16777216 ; 0xff000000
48: e3c33502 bic r3, r3, #8388608 ; 0x800000
4c: e38335fe orr r3, r3, #1065353216 ; 0x3f800000
50: ee073a90 vmov s15, r3
54: ee370ac0 vsub.f32 s0, s15, s0
58: e8bd8008 pop {r3, pc}
5c: 3f800000 svccc 0x00800000

00000000 <main>:
0: e92d4010 push {r4, lr}
4: e3a00000 mov r0, #0
8: ebfffffe bl 0 <time>
c: ebfffffe bl 0 <main>
10: e3a04064 mov r4, #100 ; 0x64
14: ebfffffe bl 38 <main+0x38>
18: e59f0018 ldr r0, [pc, #24] ; 38 <main+0x38>
1c: eeb77ac0 vcvt.f64.f32 d7, s0
20: ec532b17 vmov r2, r3, d7
24: ebfffffe bl 0 <printf>
28: e2544001 subs r4, r4, #1
2c: 1afffff8 bne 14 <main+0x14>
30: e1a00004 mov r0, r4
34: e8bd8010 pop {r4, pc}
38: 00000000 andeq r0, r0, r0

0x5c oat_rand() 0x38 main() .

22.2.
, FPU 2 .
, . 223 = 1.19e 07 oat 252 = 2.22e 16 double.
, :
#include <stdio.h>
#include <stdint.h>

union uint_float
2 .

402
22. (UNION) 22. (UNION)
{
uint32_t i;
float f;
};

float calculate_machine_epsilon(float start)


{
union uint_float v;
v.f=start;
v.i++;
return v.fstart;
}

void main()
{
printf ("%g\n", calculate_machine_epsilon(1.234567));
};

IEEE 754 -
. starting_value + machine_epsilon,
( ) ,
(oat).
union IEEE 754 . -
1 1 , , , ,
.

22.2.1. x86

22.5: MSVC 2010


tv130 = 8
_v$ = 8
_start$ = 8
_calculate_machine_epsilon PROC
fld DWORD PTR _start$[esp4]
fst DWORD PTR _v$[esp4] ;
inc DWORD PTR _v$[esp4]
fsubr DWORD PTR _v$[esp4]
fstp DWORD PTR tv130[esp4] ; \
fld DWORD PTR tv130[esp4] ; /
ret 0
_calculate_machine_epsilon ENDP

FST : (
v , ).
INC, .
FPU 32- IEEE 754, FSUBR ST0.
FSTP/FLD , .

22.2.2. ARM64

64-:
#include <stdio.h>
#include <stdint.h>

typedef union
{
uint64_t i;
double d;
} uint_double;

double calculate_machine_epsilon(double start)


{
uint_double v;

403
22. (UNION) 22. (UNION)
v.d=start;
v.i++;
return v.dstart;
}

void main()
{
printf ("%g\n", calculate_machine_epsilon(1.234567));
};

ARM64 D- FPU, ( D0)


GPR, , FPU D1, .

22.6: GCC 4.9 ARM64


calculate_machine_epsilon:
fmov x0, d0 ; double X0
add x0, x0, 1 ; X0++
fmov d1, x0 ; FPU
fsub d0, d1, d0 ;
ret

x64 SIMD- : 27.4 (. 461).

22.2.3. MIPS

MTC1 (Move To Coprocessor 1), GPR


FPU.

22.7: GCC 4.4.5 (IDA)


calculate_machine_epsilon:
mfc1 $v0, $f12
or $at, $zero ; NOP
addiu $v1, $v0, 1
mtc1 $v1, $f2
jr $ra
sub.s $f0, $f2, $f12 ; branch delay slot

22.2.4.

, - ,
, IEEE 754 union /++.

22.3.
oat ,
.

22.8: Wikipedia: http://go.yurichev.com/17364


/* Assumes that float is in the IEEE 754 single precision floating point format
* and that int is 32 bits. */
float sqrt_approx(float z)
{
int val_int = *(int*)&z; /* Same bits, but as an int */
/*
* To justify the following code, prove that
*
* ((((val_int / 2^m) b) / 2) + b) * 2^m = ((val_int 2^m) / 2) + ((b + 1) / 2) * 2^m)
*
* where
*
* b = exponent bias
* m = number of mantissa bits

404
22. (UNION) 22. (UNION)
*
* .
*/

val_int = 1 << 23; /* Subtract 2^m. */


val_int >>= 1; /* Divide by 2. */
val_int += 1 << 29; /* Add ((b + 1) / 2) * 2^m. */

return *(float*)&val_int; /* Interpret again as float */


}

, , .

1 . , , -
x
Quake III Arena.
Wikipedia: http://go.yurichev.com/17361.

405
23. 23.

23

, , , ,
.
.. callback- 1 .
:
qsort()2 , atexit()3 ;
*NIX 4 ;
: CreateThread() (win32), pthread_create() (POSIX);
win32, EnumChildWindows()5 .
Linux, , callback-: http:
//go.yurichev.com/17076
GCC callback-: http://go.yurichev.com/17077
dwm Linux,
-. - , , :
GitHub. , switch().
, qsort() . ,
, , qsort()
.
:
int (*compare)(const void *, const void *)

, :
1 /* ex3 Sorting ints with qsort */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 int comp(const void * _a, const void * _b)
7 {
8 const int *a=(const int *)_a;
9 const int *b=(const int *)_b;
10
11 if (*a==*b)
12 return 0;
13 else
14 if (*a < *b)
15 return 1;
16 else
17 return 1;
18 }
1 wikipedia
2 wikipedia
3 http://go.yurichev.com/17073
4 wikipedia
5 MSDN

406
23. 23.
19
20 int main(int argc, char* argv[])
21 {
22 int numbers[10]={1892,45,200,98,4087,5,12345,1087,88,100000};
23 int i;
24
25 /* Sort the array */
26 qsort(numbers,10,sizeof(int),comp) ;
27 for (i=0;i<9;i++)
28 printf("Number = %d\n",numbers[ i ]) ;
29 return 0;
30 }

23.1. MSVC
MSVC 2010 ( ) /Ox :
23.1: MSVC 2010: /GS- /MD
__a$ = 8 ; size = 4
__b$ = 12 ; size = 4
_comp PROC
mov eax, DWORD PTR __a$[esp4]
mov ecx, DWORD PTR __b$[esp4]
mov eax, DWORD PTR [eax]
mov ecx, DWORD PTR [ecx]
cmp eax, ecx
jne SHORT $LN4@comp
xor eax, eax
ret 0
$LN4@comp:
xor edx, edx
cmp eax, ecx
setge dl
lea eax, DWORD PTR [edx+edx1]
ret 0
_comp ENDP

_numbers$ = 40 ; size = 40
_argc$ = 8 ; size = 4
_argv$ = 12 ; size = 4
_main PROC
sub esp, 40 ; 00000028H
push esi
push OFFSET _comp
push 4
lea eax, DWORD PTR _numbers$[esp+52]
push 10 ; 0000000aH
push eax
mov DWORD PTR _numbers$[esp+60], 1892 ; 00000764H
mov DWORD PTR _numbers$[esp+64], 45 ; 0000002dH
mov DWORD PTR _numbers$[esp+68], 200 ; 000000c8H
mov DWORD PTR _numbers$[esp+72], 98 ; ffffff9eH
mov DWORD PTR _numbers$[esp+76], 4087 ; 00000ff7H
mov DWORD PTR _numbers$[esp+80], 5
mov DWORD PTR _numbers$[esp+84], 12345 ; ffffcfc7H
mov DWORD PTR _numbers$[esp+88], 1087 ; 0000043fH
mov DWORD PTR _numbers$[esp+92], 88 ; 00000058H
mov DWORD PTR _numbers$[esp+96], 100000 ; fffe7960H
call _qsort
add esp, 16 ; 00000010H

...

. , qsort() -
_comp, comp(), , ,
.

407
23. 23.
qsort() ?
MSVCR80.DLL ( DLL MSVC ):

23.2: MSVCR80.DLL
.text:7816CBF0 ; void __cdecl qsort(void *, unsigned int, unsigned int, int (__cdecl *)(const void *,
const void *))
.text:7816CBF0 public _qsort
.text:7816CBF0 _qsort proc near
.text:7816CBF0
.text:7816CBF0 lo = dword ptr 104h
.text:7816CBF0 hi = dword ptr 100h
.text:7816CBF0 var_FC = dword ptr 0FCh
.text:7816CBF0 stkptr = dword ptr 0F8h
.text:7816CBF0 lostk = dword ptr 0F4h
.text:7816CBF0 histk = dword ptr 7Ch
.text:7816CBF0 base = dword ptr 4
.text:7816CBF0 num = dword ptr 8
.text:7816CBF0 width = dword ptr 0Ch
.text:7816CBF0 comp = dword ptr 10h
.text:7816CBF0
.text:7816CBF0 sub esp, 100h

....

.text:7816CCE0 loc_7816CCE0: ; CODE XREF: _qsort+B1


.text:7816CCE0 shr eax, 1
.text:7816CCE2 imul eax, ebp
.text:7816CCE5 add eax, ebx
.text:7816CCE7 mov edi, eax
.text:7816CCE9 push edi
.text:7816CCEA push ebx
.text:7816CCEB call [esp+118h+comp]
.text:7816CCF2 add esp, 8
.text:7816CCF5 test eax, eax
.text:7816CCF7 jle short loc_7816CD04

comp . , comp.
comp(). , .
. -, qsort()
, qsort(), , , ,
.
-, callback- ,
, , ,
, .

408
23. 23.
23.1.1. MSVC + OllyDbg

OllyDbg comp() .
, comp() :

. 23.1: OllyDbg: comp()

, OllyDbg . , SP
RA qsort() ( , MSVCR100.DLL).

409
23. 23.
(F8) RETN F8 , qsort():

. 23.2: OllyDbg: qsort() comp()

410
23. 23.
comp() :

. 23.3: OllyDbg: comp()

23.1.2. MSVC + tracer

, . 10 : 1892, 45, 200, -98, 4087, 5, -12345, 1087, 88,


-100000.
CMP comp() 0x0040100C :
tracer.exe l:17_1.exe bpx=17_1.exe!0x0040100C

:
PID=4336|New process 17_1.exe
(0) 17_1.exe!0x40100c
EAX=0x00000764 EBX=0x0051f7c8 ECX=0x00000005 EDX=0x00000000
ESI=0x0051f7d8 EDI=0x0051f7b4 EBP=0x0051f794 ESP=0x0051f67c
EIP=0x0028100c
FLAGS=IF
(0) 17_1.exe!0x40100c
EAX=0x00000005 EBX=0x0051f7c8 ECX=0xfffe7960 EDX=0x00000000
ESI=0x0051f7d8 EDI=0x0051f7b4 EBP=0x0051f794 ESP=0x0051f67c
EIP=0x0028100c
FLAGS=PF ZF IF
(0) 17_1.exe!0x40100c
EAX=0x00000764 EBX=0x0051f7c8 ECX=0x00000005 EDX=0x00000000
ESI=0x0051f7d8 EDI=0x0051f7b4 EBP=0x0051f794 ESP=0x0051f67c
EIP=0x0028100c
FLAGS=CF PF ZF IF
...

EAX ECX :
EAX=0x00000764 ECX=0x00000005
EAX=0x00000005 ECX=0xfffe7960
EAX=0x00000764 ECX=0x00000005
EAX=0x0000002d ECX=0x00000005
EAX=0x00000058 ECX=0x00000005
EAX=0x0000043f ECX=0x00000005
EAX=0xffffcfc7 ECX=0x00000005
EAX=0x000000c8 ECX=0x00000005
EAX=0xffffff9e ECX=0x00000005
EAX=0x00000ff7 ECX=0x00000005
EAX=0x00000ff7 ECX=0x00000005
EAX=0xffffff9e ECX=0x00000005
EAX=0xffffff9e ECX=0x00000005
EAX=0xffffcfc7 ECX=0xfffe7960

411
23. 23.
EAX=0x00000005 ECX=0xffffcfc7
EAX=0xffffff9e ECX=0x00000005
EAX=0xffffcfc7 ECX=0xfffe7960
EAX=0xffffff9e ECX=0xffffcfc7
EAX=0xffffcfc7 ECX=0xfffe7960
EAX=0x000000c8 ECX=0x00000ff7
EAX=0x0000002d ECX=0x00000ff7
EAX=0x0000043f ECX=0x00000ff7
EAX=0x00000058 ECX=0x00000ff7
EAX=0x00000764 ECX=0x00000ff7
EAX=0x000000c8 ECX=0x00000764
EAX=0x0000002d ECX=0x00000764
EAX=0x0000043f ECX=0x00000764
EAX=0x00000058 ECX=0x00000764
EAX=0x000000c8 ECX=0x00000058
EAX=0x0000002d ECX=0x000000c8
EAX=0x0000043f ECX=0x000000c8
EAX=0x000000c8 ECX=0x00000058
EAX=0x0000002d ECX=0x000000c8
EAX=0x0000002d ECX=0x00000058

34 . , 34 10-
.

412
23. 23.
23.1.3. MSVC + tracer (code coverage)

tracer
IDA.
comp():
tracer.exe l:17_1.exe bpf=17_1.exe!0x00401000,trace:cc

.idc- IDA :

. 23.4: tracer IDA. N.B.:

(PtFuncCompare) IDA ,
qsort() .
, a b , 4, ,
32- .
, 0x401010 0x401012 ( ): -
, comp() 0, .

23.2. GCC
:

23.3: GCC
lea eax, [esp+40h+var_28]
mov [esp+40h+var_40], eax
mov [esp+40h+var_28], 764h
mov [esp+40h+var_24], 2Dh
mov [esp+40h+var_20], 0C8h
mov [esp+40h+var_1C], 0FFFFFF9Eh
mov [esp+40h+var_18], 0FF7h
mov [esp+40h+var_14], 5
mov [esp+40h+var_10], 0FFFFCFC7h
mov [esp+40h+var_C], 43Fh
mov [esp+40h+var_8], 58h
mov [esp+40h+var_4], 0FFFE7960h
mov [esp+40h+var_34], offset comp
mov [esp+40h+var_38], 4

413
23. 23.
mov [esp+40h+var_3C], 0Ah
call _qsort

comp():
public comp
comp proc near

arg_0 = dword ptr 8


arg_4 = dword ptr 0Ch

push ebp
mov ebp, esp
mov eax, [ebp+arg_4]
mov ecx, [ebp+arg_0]
mov edx, [eax]
xor eax, eax
cmp [ecx], edx
jnz short loc_8048458
pop ebp
retn
loc_8048458:
setnl al
movzx eax, al
lea eax, [eax+eax1]
pop ebp
retn
comp endp

qsort() libc.so.6, wrapper 6 qsort_r().


, , quicksort(), -
:

23.4: ( libc.so.6, glibc 2.10.1)

.text:0002DDF6 mov edx, [ebp+arg_10]


.text:0002DDF9 mov [esp+4], esi
.text:0002DDFD mov [esp], edi
.text:0002DE00 mov [esp+8], edx
.text:0002DE04 call [ebp+arg_C]
...

23.2.1. GCC + GDB ( )

, (23 (. 406)),
(b) (11- ).
-g, . -
(p): ,
/ .
(bt) Glibc -
msort_with_tmp().

23.5: GDB-
dennis@ubuntuvm:~/polygon$ gcc 17_1.c g
dennis@ubuntuvm:~/polygon$ gdb ./a.out
GNU gdb (GDB) 7.6.1ubuntu
Copyright (C) 2013 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 "i686linuxgnu".
For bug reporting instructions, please see:
6 thunk function

414
23. 23.
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dennis/polygon/a.out...done.
(gdb) b 17_1.c:11
Breakpoint 1 at 0x804845f: file 17_1.c, line 11.
(gdb) run
Starting program: /home/dennis/polygon/./a.out

Breakpoint 1, comp (_a=0xbffff0f8, _b=_b@entry=0xbffff0fc) at 17_1.c:11


11 if (*a==*b)
(gdb) p *a
$1 = 1892
(gdb) p *b
$2 = 45
(gdb) c
Continuing.

Breakpoint 1, comp (_a=0xbffff104, _b=_b@entry=0xbffff108) at 17_1.c:11


11 if (*a==*b)
(gdb) p *a
$3 = 98
(gdb) p *b
$4 = 4087
(gdb) bt
#0 comp (_a=0xbffff0f8, _b=_b@entry=0xbffff0fc) at 17_1.c:11
#1 0xb7e42872 in msort_with_tmp (p=p@entry=0xbffff07c, b=b@entry=0xbffff0f8, n=n@entry=2)
at msort.c:65
#2 0xb7e4273e in msort_with_tmp (n=2, b=0xbffff0f8, p=0xbffff07c) at msort.c:45
#3 msort_with_tmp (p=p@entry=0xbffff07c, b=b@entry=0xbffff0f8, n=n@entry=5) at msort.c:53
#4 0xb7e4273e in msort_with_tmp (n=5, b=0xbffff0f8, p=0xbffff07c) at msort.c:45
#5 msort_with_tmp (p=p@entry=0xbffff07c, b=b@entry=0xbffff0f8, n=n@entry=10) at msort.c:53
#6 0xb7e42cef in msort_with_tmp (n=10, b=0xbffff0f8, p=0xbffff07c) at msort.c:45
#7 __GI_qsort_r (b=b@entry=0xbffff0f8, n=n@entry=10, s=s@entry=4, cmp=cmp@entry=0x804844d <comp>,
arg=arg@entry=0x0) at msort.c:297
#8 0xb7e42dcf in __GI_qsort (b=0xbffff0f8, n=10, s=4, cmp=0x804844d <comp>) at msort.c:307
#9 0x0804850d in main (argc=1, argv=0xbffff1c4) at 17_1.c:26
(gdb)

23.2.2. GCC + GDB ( )

, comp() (disas),
CMP (b) .
(info registers). (bt), :
comp() .

23.6: GDB-
dennis@ubuntuvm:~/polygon$ gcc 17_1.c
dennis@ubuntuvm:~/polygon$ gdb ./a.out
GNU gdb (GDB) 7.6.1ubuntu
Copyright (C) 2013 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 "i686linuxgnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dennis/polygon/a.out...(no debugging symbols found)...done.
(gdb) set disassemblyflavor intel
(gdb) disas comp
Dump of assembler code for function comp:
0x0804844d <+0>: push ebp
0x0804844e <+1>: mov ebp,esp
0x08048450 <+3>: sub esp,0x10
0x08048453 <+6>: mov eax,DWORD PTR [ebp+0x8]
0x08048456 <+9>: mov DWORD PTR [ebp0x8],eax
0x08048459 <+12>: mov eax,DWORD PTR [ebp+0xc]
0x0804845c <+15>: mov DWORD PTR [ebp0x4],eax

415
23. 23.
0x0804845f <+18>: mov eax,DWORD PTR [ebp0x8]
0x08048462 <+21>: mov edx,DWORD PTR [eax]
0x08048464 <+23>: mov eax,DWORD PTR [ebp0x4]
0x08048467 <+26>: mov eax,DWORD PTR [eax]
0x08048469 <+28>: cmp edx,eax
0x0804846b <+30>: jne 0x8048474 <comp+39>
0x0804846d <+32>: mov eax,0x0
0x08048472 <+37>: jmp 0x804848e <comp+65>
0x08048474 <+39>: mov eax,DWORD PTR [ebp0x8]
0x08048477 <+42>: mov edx,DWORD PTR [eax]
0x08048479 <+44>: mov eax,DWORD PTR [ebp0x4]
0x0804847c <+47>: mov eax,DWORD PTR [eax]
0x0804847e <+49>: cmp edx,eax
0x08048480 <+51>: jge 0x8048489 <comp+60>
0x08048482 <+53>: mov eax,0xffffffff
0x08048487 <+58>: jmp 0x804848e <comp+65>
0x08048489 <+60>: mov eax,0x1
0x0804848e <+65>: leave
0x0804848f <+66>: ret
End of assembler dump.
(gdb) b *0x08048469
Breakpoint 1 at 0x8048469
(gdb) run
Starting program: /home/dennis/polygon/./a.out

Breakpoint 1, 0x08048469 in comp ()


(gdb) info registers
eax 0x2d 45
ecx 0xbffff0f8 1073745672
edx 0x764 1892
ebx 0xb7fc0000 1208221696
esp 0xbfffeeb8 0xbfffeeb8
ebp 0xbfffeec8 0xbfffeec8
esi 0xbffff0fc 1073745668
edi 0xbffff010 1073745904
eip 0x8048469 0x8048469 <comp+28>
eflags 0x286 [ PF SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) c
Continuing.

Breakpoint 1, 0x08048469 in comp ()


(gdb) info registers
eax 0xff7 4087
ecx 0xbffff104 1073745660
edx 0xffffff9e 98
ebx 0xb7fc0000 1208221696
esp 0xbfffee58 0xbfffee58
ebp 0xbfffee68 0xbfffee68
esi 0xbffff108 1073745656
edi 0xbffff010 1073745904
eip 0x8048469 0x8048469 <comp+28>
eflags 0x282 [ SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) c
Continuing.

Breakpoint 1, 0x08048469 in comp ()


(gdb) info registers
eax 0xffffff9e 98

416
23. 23.
ecx 0xbffff100 1073745664
edx 0xc8 200
ebx 0xb7fc0000 1208221696
esp 0xbfffeeb8 0xbfffeeb8
ebp 0xbfffeec8 0xbfffeec8
esi 0xbffff104 1073745660
edi 0xbffff010 1073745904
eip 0x8048469 0x8048469 <comp+28>
eflags 0x286 [ PF SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) bt
#0 0x08048469 in comp ()
#1 0xb7e42872 in msort_with_tmp (p=p@entry=0xbffff07c, b=b@entry=0xbffff0f8, n=n@entry=2)
at msort.c:65
#2 0xb7e4273e in msort_with_tmp (n=2, b=0xbffff0f8, p=0xbffff07c) at msort.c:45
#3 msort_with_tmp (p=p@entry=0xbffff07c, b=b@entry=0xbffff0f8, n=n@entry=5) at msort.c:53
#4 0xb7e4273e in msort_with_tmp (n=5, b=0xbffff0f8, p=0xbffff07c) at msort.c:45
#5 msort_with_tmp (p=p@entry=0xbffff07c, b=b@entry=0xbffff0f8, n=n@entry=10) at msort.c:53
#6 0xb7e42cef in msort_with_tmp (n=10, b=0xbffff0f8, p=0xbffff07c) at msort.c:45
#7 __GI_qsort_r (b=b@entry=0xbffff0f8, n=n@entry=10, s=s@entry=4, cmp=cmp@entry=0x804844d <comp>,
arg=arg@entry=0x0) at msort.c:297
#8 0xb7e42dcf in __GI_qsort (b=0xbffff0f8, n=10, s=4, cmp=0x804844d <comp>) at msort.c:307
#9 0x0804850d in main ()

417
24. 64- 32- 24. 64- 32-

24

64- 32-

, GPR- 32-, 64- 32- 1 .

24.1. 64-

#include <stdint.h>

uint64_t f ()
{
return 0x1234567890ABCDEF;
};

24.1.1. x86

64- 32- EDX:EAX.

24.1: MSVC 2010


_f PROC
mov eax, 1867788817 ; 90abcdefH
mov edx, 305419896 ; 12345678H
ret 0
_f ENDP

24.1.2. ARM

64- R0-R1 (R1 R0 ):

24.2: Keil 6/2013 ( ARM)


||f|| PROC
LDR r0,|L0.12|
LDR r1,|L0.16|
BX lr
ENDP

|L0.12|
DCD 0x90abcdef
|L0.16|
DCD 0x12345678

1 , 16- , 32- 16- : 53.4 (. 619)

418
24. 64- 32- 24. 64- 32-
24.1.3. MIPS

64- V0-V1 ($2-$3) (V0 ($2) V1 ($3)


):

24.3: GCC 4.4.5 (assembly listing)


li $3,1867841536 # 0xffffffff90ab0000
li $2,305397760 # 0x12340000
ori $3,$3,0xcdef
j $31
ori $2,$2,0x5678

24.4: GCC 4.4.5 (IDA)


lui $v1, 0x90AB
lui $v0, 0x1234
li $v1, 0x90ABCDEF
jr $ra
li $v0, 0x12345678

24.2. , ,

#include <stdint.h>

uint64_t f_add (uint64_t a, uint64_t b)


{
return a+b;
};

void f_add_test ()
{
#ifdef __GNUC__
printf ("%lld\n", f_add(12345678901234, 23456789012345));
#else
printf ("%I64d\n", f_add(12345678901234, 23456789012345));
#endif
};

uint64_t f_sub (uint64_t a, uint64_t b)


{
return ab;
};

24.2.1. x86

24.5: MSVC 2012 /Ob1


_a$ = 8 ; size = 8
_b$ = 16 ; size = 8
_f_add PROC
mov eax, DWORD PTR _a$[esp4]
add eax, DWORD PTR _b$[esp4]
mov edx, DWORD PTR _a$[esp]
adc edx, DWORD PTR _b$[esp]
ret 0
_f_add ENDP

_f_add_test PROC
push 5461 ; 00001555H
push 1972608889 ; 75939f79H
push 2874 ; 00000b3aH
push 1942892530 ; 73ce2ff_subH
call _f_add
push edx

419
24. 64- 32- 24. 64- 32-
push eax
push OFFSET $SG1436 ; '%I64d', 0aH, 00H
call _printf
add esp, 28
ret 0
_f_add_test ENDP

_f_sub PROC
mov eax, DWORD PTR _a$[esp4]
sub eax, DWORD PTR _b$[esp4]
mov edx, DWORD PTR _a$[esp]
sbb edx, DWORD PTR _b$[esp]
ret 0
_f_sub ENDP

f_add_test() , 64- 32- , ,


.

, 32 . , CF. -
ADC , CF = 1 .

. SUB CF, -
SBB : , .

, f_add() printf().

24.6: GCC 4.8.1 -O1 -fno-inline


_f_add:
mov eax, DWORD PTR [esp+12]
mov edx, DWORD PTR [esp+16]
add eax, DWORD PTR [esp+4]
adc edx, DWORD PTR [esp+8]
ret

_f_add_test:
sub esp, 28
mov DWORD PTR [esp+8], 1972608889 ; 75939f79H
mov DWORD PTR [esp+12], 5461 ; 00001555H
mov DWORD PTR [esp], 1942892530 ; 73ce2ff_subH
mov DWORD PTR [esp+4], 2874 ; 00000b3aH
call _f_add
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp+8], edx
mov DWORD PTR [esp], OFFSET FLAT:LC0 ; "%lld\12\0"
call _printf
add esp, 28
ret

_f_sub:
mov eax, DWORD PTR [esp+4]
mov edx, DWORD PTR [esp+8]
sub eax, DWORD PTR [esp+12]
sbb edx, DWORD PTR [esp+16]
ret

GCC .

24.2.2. ARM

24.7: Keil 6/2013 ( ARM)


f_add PROC
ADDS r0,r0,r2
ADC r1,r1,r3
BX lr

420
24. 64- 32- 24. 64- 32-
ENDP

f_sub PROC
SUBS r0,r0,r2
SBC r1,r1,r3
BX lr
ENDP

f_add_test PROC
PUSH {r4,lr}
LDR r2,|L0.68| ; 0x75939f79
LDR r3,|L0.72| ; 0x00001555
LDR r0,|L0.76| ; 0x73ce2ff2
LDR r1,|L0.80| ; 0x00000b3a
BL f_add
POP {r4,lr}
MOV r2,r0
MOV r3,r1
ADR r0,|L0.84| ; "%I64d\n"
B __2printf
ENDP

|L0.68|
DCD 0x75939f79
|L0.72|
DCD 0x00001555
|L0.76|
DCD 0x73ce2ff2
|L0.80|
DCD 0x00000b3a
|L0.84|
DCB "%I64d\n",0

64- R0 R1, R2 R3. ARM


ADC ( ) SBC (subtract with carry ).
: /, ADDS SUBS -S. -
-S set ags ( ), ( ) -
ADC/SBC.
-S (ADD SUB).

24.2.3. MIPS

24.8: GCC 4.4.5 (IDA)


f_add:
; $a0 a
; $a1 a
; $a2 b
; $a3 b
addu $v1, $a3, $a1 ;
addu $a0, $a2, $a0 ;
; ?
; $v0 1,
sltu $v0, $v1, $a3
jr $ra
; 1 ,
addu $v0, $a0 ; branch delay slot
; $v0
; $v1

f_sub:
; $a0 a
; $a1 a
; $a2 b
; $a3 b
subu $v1, $a1, $a3 ;
subu $v0, $a0, $a2 ;

421
24. 64- 32- 24. 64- 32-
; ?
; $a0 1,
sltu $a1, $v1
jr $ra
; 1 ,
subu $v0, $a1 ; branch delay slot
; $v0
; $v1

f_add_test:

var_10 = 0x10
var_4 = 4

lui $gp, (__gnu_local_gp >> 16)


addiu $sp, 0x20
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x20+var_4($sp)
sw $gp, 0x20+var_10($sp)
lui $a1, 0x73CE
lui $a3, 0x7593
li $a0, 0xB3A
li $a3, 0x75939F79
li $a2, 0x1555
jal f_add
li $a1, 0x73CE2FF2
lw $gp, 0x20+var_10($sp)
lui $a0, ($LC0 >> 16) # "%lld\n"
lw $t9, (printf & 0xFFFF)($gp)
lw $ra, 0x20+var_4($sp)
la $a0, ($LC0 & 0xFFFF) # "%lld\n"
move $a3, $v1
move $a2, $v0
jr $t9
addiu $sp, 0x20

$LC0: .ascii "%lld\n"<0>

MIPS , .
ADC SBB x86. , ,
( SLTU), 1 0. 1 0
, .

24.3. ,

#include <stdint.h>

uint64_t f_mul (uint64_t a, uint64_t b)


{
return a*b;
};

uint64_t f_div (uint64_t a, uint64_t b)


{
return a/b;
};

uint64_t f_rem (uint64_t a, uint64_t b)


{
return a % b;
};

24.3.1. x86

422
24. 64- 32- 24. 64- 32-
24.9: MSVC 2013 /Ob1
_a$ = 8 ; size = 8
_b$ = 16 ; size = 8
_f_mul PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _b$[ebp+4]
push eax
mov ecx, DWORD PTR _b$[ebp]
push ecx
mov edx, DWORD PTR _a$[ebp+4]
push edx
mov eax, DWORD PTR _a$[ebp]
push eax
call __allmul ; long long multiplication ( long long)
pop ebp
ret 0
_f_mul ENDP

_a$ = 8 ; size = 8
_b$ = 16 ; size = 8
_f_div PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _b$[ebp+4]
push eax
mov ecx, DWORD PTR _b$[ebp]
push ecx
mov edx, DWORD PTR _a$[ebp+4]
push edx
mov eax, DWORD PTR _a$[ebp]
push eax
call __aulldiv ; unsigned long long division ( long long)
pop ebp
ret 0
_f_div ENDP

_a$ = 8 ; size = 8
_b$ = 16 ; size = 8
_f_rem PROC
push ebp
mov ebp, esp
mov eax, DWORD PTR _b$[ebp+4]
push eax
mov ecx, DWORD PTR _b$[ebp]
push ecx
mov edx, DWORD PTR _a$[ebp+4]
push edx
mov eax, DWORD PTR _a$[ebp]
push eax
call __aullrem ; unsigned long long remainder ( )
pop ebp
ret 0
_f_rem ENDP

, ,
, .
, : E (. 981).
24.10: GCC 4.8.1 -fno-inline
_f_mul:
push ebx
mov edx, DWORD PTR [esp+8]
mov eax, DWORD PTR [esp+16]
mov ebx, DWORD PTR [esp+12]
mov ecx, DWORD PTR [esp+20]
imul ebx, eax
imul ecx, edx
mul edx

423
24. 64- 32- 24. 64- 32-
add ecx, ebx
add edx, ecx
pop ebx
ret

_f_div:
sub esp, 28
mov eax, DWORD PTR [esp+40]
mov edx, DWORD PTR [esp+44]
mov DWORD PTR [esp+8], eax
mov eax, DWORD PTR [esp+32]
mov DWORD PTR [esp+12], edx
mov edx, DWORD PTR [esp+36]
mov DWORD PTR [esp], eax
mov DWORD PTR [esp+4], edx
call ___udivdi3 ; unsigned division ( )
add esp, 28
ret

_f_rem:
sub esp, 28
mov eax, DWORD PTR [esp+40]
mov edx, DWORD PTR [esp+44]
mov DWORD PTR [esp+8], eax
mov eax, DWORD PTR [esp+32]
mov DWORD PTR [esp+12], edx
mov edx, DWORD PTR [esp+36]
mov DWORD PTR [esp], eax
mov DWORD PTR [esp+4], edx
call ___umoddi3 ; unsigned modulo ( )
add esp, 28
ret

GCC , , ,
. GCC : D (. 980).

24.3.2. ARM

Keil Thumb :

24.11: Keil 6/2013 ( Thumb)


||f_mul|| PROC
PUSH {r4,lr}
BL __aeabi_lmul
POP {r4,pc}
ENDP

||f_div|| PROC
PUSH {r4,lr}
BL __aeabi_uldivmod
POP {r4,pc}
ENDP

||f_rem|| PROC
PUSH {r4,lr}
BL __aeabi_uldivmod
MOVS r0,r2
MOVS r1,r3
POP {r4,pc}
ENDP

Keil ARM, , 64- :

24.12: Keil 6/2013 ( ARM)


||f_mul|| PROC
PUSH {r4,lr}
UMULL r12,r4,r0,r2

424
24. 64- 32- 24. 64- 32-
MLA r1,r2,r1,r4
MLA r1,r0,r3,r1
MOV r0,r12
POP {r4,pc}
ENDP

||f_div|| PROC
PUSH {r4,lr}
BL __aeabi_uldivmod
POP {r4,pc}
ENDP

||f_rem|| PROC
PUSH {r4,lr}
BL __aeabi_uldivmod
MOV r0,r2
MOV r1,r3
POP {r4,pc}
ENDP

24.3.3. MIPS

GCC MIPS 64- , 64- -


:
24.13: GCC 4.4.5 (IDA)
f_mul:
mult $a2, $a1
mflo $v0
or $at, $zero ; NOP
or $at, $zero ; NOP
mult $a0, $a3
mflo $a0
addu $v0, $a0
or $at, $zero ; NOP
multu $a3, $a1
mfhi $a2
mflo $v1
jr $ra
addu $v0, $a2

f_div:

var_10 = 0x10
var_4 = 4

lui $gp, (__gnu_local_gp >> 16)


addiu $sp, 0x20
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x20+var_4($sp)
sw $gp, 0x20+var_10($sp)
lw $t9, (__udivdi3 & 0xFFFF)($gp)
or $at, $zero
jalr $t9
or $at, $zero
lw $ra, 0x20+var_4($sp)
or $at, $zero
jr $ra
addiu $sp, 0x20

f_rem:

var_10 = 0x10
var_4 = 4

lui $gp, (__gnu_local_gp >> 16)


addiu $sp, 0x20
la $gp, (__gnu_local_gp & 0xFFFF)

425
24. 64- 32- 24. 64- 32-
sw $ra, 0x20+var_4($sp)
sw $gp, 0x20+var_10($sp)
lw $t9, (__umoddi3 & 0xFFFF)($gp)
or $at, $zero
jalr $t9
or $at, $zero
lw $ra, 0x20+var_4($sp)
or $at, $zero
jr $ra
addiu $sp, 0x20

NOP-, delay slot- ( -


).

24.4.

#include <stdint.h>

uint64_t f (uint64_t a)
{
return a>>7;
};

24.4.1. x86

24.14: MSVC 2012 /Ob1


_a$ = 8 ; size = 8
_f PROC
mov eax, DWORD PTR _a$[esp4]
mov edx, DWORD PTR _a$[esp]
shrd eax, edx, 7
shr edx, 7
ret 0
_f ENDP

24.15: GCC 4.8.1 -fno-inline


_f:
mov edx, DWORD PTR [esp+8]
mov eax, DWORD PTR [esp+4]
shrd eax, edx, 7
shr edx, 7
ret

: , . -
SHRD, EDX 7 , EAX, ..
. SHR: ,
.

24.4.2. ARM

ARM SHRD x86, Keil ,


:

24.16: Keil 6/2013 ( ARM)


||f|| PROC
LSR r0,r0,#7
ORR r0,r0,r1,LSL #25
LSR r1,r1,#7
BX lr
ENDP

426
24. 64- 32- 24. 64- 32-
24.17: Keil 6/2013 ( Thumb)
||f|| PROC
LSLS r2,r1,#25
LSRS r0,r0,#7
ORRS r0,r0,r2
LSRS r1,r1,#7
BX lr
ENDP

24.4.3. MIPS

GCC MIPS , Keil Thumb:

24.18: GCC 4.4.5 (IDA)


f:
sll $v0, $a0, 25
srl $v1, $a1, 7
or $v1, $v0, $v1
jr $ra
srl $v0, $a0, 7

24.5. 32- 64-

#include <stdint.h>

int64_t f (int32_t a)
{
return a;
};

24.5.1. x86

24.19: MSVC 2012


_a$ = 8
_f PROC
mov eax, DWORD PTR _a$[esp4]
cdq
ret 0
_f ENDP

32- 64- . -
: 0 .
: - . CDQ,
EAX, 64-, EDX:EAX . ,
CDQ EAX ( EAX) ,
32 EDX 0 1. - MOVSX.

24.5.2. ARM

24.20: Keil 6/2013 ( ARM)


||f|| PROC
ASR r1,r0,#31
BX lr
ENDP

427
24. 64- 32- 24. 64- 32-
Keil ARM : () 31 . ,
MSB, .
ASR r1,r0,#31, R1 0xFFFFFFFF , 0 .
R1 64- .
, MSB ( ) R0 32-
64- .

24.5.3. MIPS

GCC MIPS , Keil ARM:

24.21: GCC 4.4.5 (IDA)


f:
sra $v0, $a0, 31
jr $ra
move $v1, $a0

428
25. SIMD 25. SIMD

25

SIMD

SIMD : Single Instruction, Multiple Data.


, .
FPU, x86.
SIMD x86 MMX. 8 64- MM0-MM7.
MMX- 2 32- , 4 16- 8 . , -
MMX-, 8 8- .
, , .
, , , -
, . , --
, MMX . , SIMD
(saturation). , -
(underow) , SIMD , , ,
, ..
MMX , FPU-.
FPU MMX . , Intel ,

, FPU . ,
MMX + + , MMX = .
SSE 128 , FPU.
AVX 256 .
.
, (memcpy), (memcmp), .
: DES, 64- , 56- , -
64- . DES
, , , , .
bitslice DES1 . , x86
unsigned int 32 , 32- -
, 64+56 unsigned int.
/ Oracle RDBMS ( DES),
bitslice DES SSE2 AVX 128 256 -:
http://go.yurichev.com/17313

25.1.
2 , , ,
. , - .
.
1 http://go.yurichev.com/17329
2 Wikipedia: vectorization

429
25. SIMD 25. SIMD
: -
Cray Y-MP 1988, - Cray Y-MP EL 3 .
:
for (i = 0; i < 1024; i++)
{
C[i] = A[i]*B[i];
}

A B, C.
, 32- int, 4 128-
XMM-, B XMM- PMULLD ( DWORD
) PMULHW ( DWORD
), 4 64- .
, 1024/4 1024, 4 , , , .

25.1.1.

, , Intel C++4 .
:
int f (int sz, int *ar1, int *ar2, int *ar3)
{
for (int i=0; i<sz; i++)
ar3[i]=ar1[i]+ar2[i];

return 0;
};

Intel C++

Intel C++ 11.1.051 win32:


icl intel.cpp /QaxSSE2 /Faintel.asm /Ox
( IDA):
; int __cdecl f(int, int *, int *, int *)
public ?f@@YAHHPAH00@Z
?f@@YAHHPAH00@Z proc near

var_10 = dword ptr 10h


sz = dword ptr 4
ar1 = dword ptr 8
ar2 = dword ptr 0Ch
ar3 = dword ptr 10h

push edi
push esi
push ebx
push esi
mov edx, [esp+10h+sz]
test edx, edx
jle loc_15B
mov eax, [esp+10h+ar3]
cmp edx, 6
jle loc_143
cmp eax, [esp+10h+ar2]
jbe short loc_36
mov esi, [esp+10h+ar2]
sub esi, eax
lea ecx, ds:0[edx*4]
neg esi
3 . : http://go.yurichev.com/17081
4 , Intel C++ : Excerpt: Effective Automatic Vectorization

430
25. SIMD 25. SIMD
cmp ecx, esi
jbe short loc_55

loc_36: ; CODE XREF: f(int,int *,int *,int *)+21


cmp eax, [esp+10h+ar2]
jnb loc_143
mov esi, [esp+10h+ar2]
sub esi, eax
lea ecx, ds:0[edx*4]
cmp esi, ecx
jb loc_143

loc_55: ; CODE XREF: f(int,int *,int *,int *)+34


cmp eax, [esp+10h+ar1]
jbe short loc_67
mov esi, [esp+10h+ar1]
sub esi, eax
neg esi
cmp ecx, esi
jbe short loc_7F

loc_67: ; CODE XREF: f(int,int *,int *,int *)+59


cmp eax, [esp+10h+ar1]
jnb loc_143
mov esi, [esp+10h+ar1]
sub esi, eax
cmp esi, ecx
jb loc_143

loc_7F: ; CODE XREF: f(int,int *,int *,int *)+65


mov edi, eax ; edi = ar1
and edi, 0Fh ; ar 16- ?
jz short loc_9A ;
test edi, 3
jnz loc_162
neg edi
add edi, 10h
shr edi, 2

loc_9A: ; CODE XREF: f(int,int *,int *,int *)+84


lea ecx, [edi+4]
cmp edx, ecx
jl loc_162
mov ecx, edx
sub ecx, edi
and ecx, 3
neg ecx
add ecx, edx
test edi, edi
jbe short loc_D6
mov ebx, [esp+10h+ar2]
mov [esp+10h+var_10], ecx
mov ecx, [esp+10h+ar1]
xor esi, esi

loc_C1: ; CODE XREF: f(int,int *,int *,int *)+CD


mov edx, [ecx+esi*4]
add edx, [ebx+esi*4]
mov [eax+esi*4], edx
inc esi
cmp esi, edi
jb short loc_C1
mov ecx, [esp+10h+var_10]
mov edx, [esp+10h+sz]

loc_D6: ; CODE XREF: f(int,int *,int *,int *)+B2


mov esi, [esp+10h+ar2]
lea esi, [esi+edi*4] ; ar2+i*4 16- ?
test esi, 0Fh
jz short loc_109 ; !

431
25. SIMD 25. SIMD
mov ebx, [esp+10h+ar1]
mov esi, [esp+10h+ar2]

loc_ED: ; CODE XREF: f(int,int *,int *,int *)+105


movdqu xmm1, xmmword ptr [ebx+edi*4] ; ar1+i*4
movdqu xmm0, xmmword ptr [esi+edi*4] ; ar2+i*4 16- ,
XMM0
paddd xmm1, xmm0
movdqa xmmword ptr [eax+edi*4], xmm1 ; ar3+i*4
add edi, 4
cmp edi, ecx
jb short loc_ED
jmp short loc_127

loc_109: ; CODE XREF: f(int,int *,int *,int *)+E3


mov ebx, [esp+10h+ar1]
mov esi, [esp+10h+ar2]

loc_111: ; CODE XREF: f(int,int *,int *,int *)+125


movdqu xmm0, xmmword ptr [ebx+edi*4]
paddd xmm0, xmmword ptr [esi+edi*4]
movdqa xmmword ptr [eax+edi*4], xmm0
add edi, 4
cmp edi, ecx
jb short loc_111

loc_127: ; CODE XREF: f(int,int *,int *,int *)+107


; f(int,int *,int *,int *)+164
cmp ecx, edx
jnb short loc_15B
mov esi, [esp+10h+ar1]
mov edi, [esp+10h+ar2]

loc_133: ; CODE XREF: f(int,int *,int *,int *)+13F


mov ebx, [esi+ecx*4]
add ebx, [edi+ecx*4]
mov [eax+ecx*4], ebx
inc ecx
cmp ecx, edx
jb short loc_133
jmp short loc_15B

loc_143: ; CODE XREF: f(int,int *,int *,int *)+17


; f(int,int *,int *,int *)+3A ...
mov esi, [esp+10h+ar1]
mov edi, [esp+10h+ar2]
xor ecx, ecx

loc_14D: ; CODE XREF: f(int,int *,int *,int *)+159


mov ebx, [esi+ecx*4]
add ebx, [edi+ecx*4]
mov [eax+ecx*4], ebx
inc ecx
cmp ecx, edx
jb short loc_14D

loc_15B: ; CODE XREF: f(int,int *,int *,int *)+A


; f(int,int *,int *,int *)+129 ...
xor eax, eax
pop ecx
pop ebx
pop esi
pop edi
retn

loc_162: ; CODE XREF: f(int,int *,int *,int *)+8C


; f(int,int *,int *,int *)+9F
xor ecx, ecx
jmp short loc_127
?f@@YAHHPAH00@Z endp

432
25. SIMD 25. SIMD
, SSE2 :
MOVDQU (Move Unaligned Double Quadword) 16 XMM- .
PADDD (Add Packed Integers) 4 32- .
, , ,
32 . PADDD ,
16- . , 5 .
MOVDQA (Move Aligned Double Quadword) MOVDQU,
16- . , . MOVDQA MOVDQU,
.
, SSE2- 4
int ar3 16- .
, ar2 16- , :
movdqu xmm0, xmmword ptr [ebx+edi*4] ; ar1+i*4
paddd xmm0, xmmword ptr [esi+edi*4] ; ar2+i*4
movdqa xmmword ptr [eax+edi*4], xmm0 ; ar3+i*4

, ar2 XMM0 MOVDQU, ,


:
movdqu xmm1, xmmword ptr [ebx+edi*4] ; ar1+i*4
movdqu xmm0, xmmword ptr [esi+edi*4] ; ar2+i*4 16- ,
XMM0
paddd xmm1, xmm0
movdqa xmmword ptr [eax+edi*4], xmm1 ; ar3+i*4

, , , SSE2.

GCC

GCC - 6 , -O3 SSE2: -msse2.


(GCC 4.4.1):
; f(int, int *, int *, int *)
public _Z1fiPiS_S_
_Z1fiPiS_S_ proc near

var_18 = dword ptr 18h


var_14 = dword ptr 14h
var_10 = dword ptr 10h
arg_0 = dword ptr 8
arg_4 = dword ptr 0Ch
arg_8 = dword ptr 10h
arg_C = dword ptr 14h

push ebp
mov ebp, esp
push edi
push esi
push ebx
sub esp, 0Ch
mov ecx, [ebp+arg_0]
mov esi, [ebp+arg_4]
mov edi, [ebp+arg_8]
mov ebx, [ebp+arg_C]
test ecx, ecx
jle short loc_80484D8
cmp ecx, 6
lea eax, [ebx+10h]
ja short loc_80484E8

loc_80484C1: ; CODE XREF: f(int,int *,int *,int *)+4B


; f(int,int *,int *,int *)+61 ...
5 . : Wikipedia:
6 GCC: http://go.yurichev.com/17083

433
25. SIMD 25. SIMD
xor eax, eax
nop
lea esi, [esi+0]

loc_80484C8: ; CODE XREF: f(int,int *,int *,int *)+36


mov edx, [edi+eax*4]
add edx, [esi+eax*4]
mov [ebx+eax*4], edx
add eax, 1
cmp eax, ecx
jnz short loc_80484C8

loc_80484D8: ; CODE XREF: f(int,int *,int *,int *)+17


; f(int,int *,int *,int *)+A5
add esp, 0Ch
xor eax, eax
pop ebx
pop esi
pop edi
pop ebp
retn

align 8

loc_80484E8: ; CODE XREF: f(int,int *,int *,int *)+1F


test bl, 0Fh
jnz short loc_80484C1
lea edx, [esi+10h]
cmp ebx, edx
jbe loc_8048578

loc_80484F8: ; CODE XREF: f(int,int *,int *,int *)+E0


lea edx, [edi+10h]
cmp ebx, edx
ja short loc_8048503
cmp edi, eax
jbe short loc_80484C1

loc_8048503: ; CODE XREF: f(int,int *,int *,int *)+5D


mov eax, ecx
shr eax, 2
mov [ebp+var_14], eax
shl eax, 2
test eax, eax
mov [ebp+var_10], eax
jz short loc_8048547
mov [ebp+var_18], ecx
mov ecx, [ebp+var_14]
xor eax, eax
xor edx, edx
nop

loc_8048520: ; CODE XREF: f(int,int *,int *,int *)+9B


movdqu xmm1, xmmword ptr [edi+eax]
movdqu xmm0, xmmword ptr [esi+eax]
add edx, 1
paddd xmm0, xmm1
movdqa xmmword ptr [ebx+eax], xmm0
add eax, 10h
cmp edx, ecx
jb short loc_8048520
mov ecx, [ebp+var_18]
mov eax, [ebp+var_10]
cmp ecx, eax
jz short loc_80484D8

loc_8048547: ; CODE XREF: f(int,int *,int *,int *)+73


lea edx, ds:0[eax*4]
add esi, edx
add edi, edx

434
25. SIMD 25. SIMD
add ebx, edx
lea esi, [esi+0]

loc_8048558: ; CODE XREF: f(int,int *,int *,int *)+CC


mov edx, [edi]
add eax, 1
add edi, 4
add edx, [esi]
add esi, 4
mov [ebx], edx
add ebx, 4
cmp ecx, eax
jg short loc_8048558
add esp, 0Ch
xor eax, eax
pop ebx
pop esi
pop edi
pop ebp
retn

loc_8048578: ; CODE XREF: f(int,int *,int *,int *)+52


cmp eax, esi
jnb loc_80484C1
jmp loc_80484F8
_Z1fiPiS_S_ endp

, , Intel C++.

25.1.2.

memcpy() (14.2 (. 188)):


#include <stdio.h>

void my_memcpy (unsigned char* dst, unsigned char* src, size_t cnt)
{
size_t i;
for (i=0; i<cnt; i++)
dst[i]=src[i];
};

GCC 4.9.1:

25.1: GCC 4.9.1 x64


my_memcpy:
; RDI =
; RSI =
; RDX =
test rdx, rdx
je .L41
lea rax, [rdi+16]
cmp rsi, rax
lea rax, [rsi+16]
setae cl
cmp rdi, rax
setae al
or cl, al
je .L13
cmp rdx, 22
jbe .L13
mov rcx, rsi
push rbp
push rbx
neg rcx
and ecx, 15
cmp rcx, rdx
cmova rcx, rdx

435
25. SIMD 25. SIMD
xor eax, eax
test rcx, rcx
je .L4
movzx eax, BYTE PTR [rsi]
cmp rcx, 1
mov BYTE PTR [rdi], al
je .L15
movzx eax, BYTE PTR [rsi+1]
cmp rcx, 2
mov BYTE PTR [rdi+1], al
je .L16
movzx eax, BYTE PTR [rsi+2]
cmp rcx, 3
mov BYTE PTR [rdi+2], al
je .L17
movzx eax, BYTE PTR [rsi+3]
cmp rcx, 4
mov BYTE PTR [rdi+3], al
je .L18
movzx eax, BYTE PTR [rsi+4]
cmp rcx, 5
mov BYTE PTR [rdi+4], al
je .L19
movzx eax, BYTE PTR [rsi+5]
cmp rcx, 6
mov BYTE PTR [rdi+5], al
je .L20
movzx eax, BYTE PTR [rsi+6]
cmp rcx, 7
mov BYTE PTR [rdi+6], al
je .L21
movzx eax, BYTE PTR [rsi+7]
cmp rcx, 8
mov BYTE PTR [rdi+7], al
je .L22
movzx eax, BYTE PTR [rsi+8]
cmp rcx, 9
mov BYTE PTR [rdi+8], al
je .L23
movzx eax, BYTE PTR [rsi+9]
cmp rcx, 10
mov BYTE PTR [rdi+9], al
je .L24
movzx eax, BYTE PTR [rsi+10]
cmp rcx, 11
mov BYTE PTR [rdi+10], al
je .L25
movzx eax, BYTE PTR [rsi+11]
cmp rcx, 12
mov BYTE PTR [rdi+11], al
je .L26
movzx eax, BYTE PTR [rsi+12]
cmp rcx, 13
mov BYTE PTR [rdi+12], al
je .L27
movzx eax, BYTE PTR [rsi+13]
cmp rcx, 15
mov BYTE PTR [rdi+13], al
jne .L28
movzx eax, BYTE PTR [rsi+14]
mov BYTE PTR [rdi+14], al
mov eax, 15
.L4:
mov r10, rdx
lea r9, [rdx1]
sub r10, rcx
lea r8, [r1016]
sub r9, rcx
shr r8, 4
add r8, 1

436
25. SIMD 25. SIMD
mov r11, r8
sal r11, 4
cmp r9, 14
jbe .L6
lea rbp, [rsi+rcx]
xor r9d, r9d
add rcx, rdi
xor ebx, ebx
.L7:
movdqa xmm0, XMMWORD PTR [rbp+0+r9]
add rbx, 1
movups XMMWORD PTR [rcx+r9], xmm0
add r9, 16
cmp rbx, r8
jb .L7
add rax, r11
cmp r10, r11
je .L1
.L6:
movzx ecx, BYTE PTR [rsi+rax]
mov BYTE PTR [rdi+rax], cl
lea rcx, [rax+1]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+1+rax]
mov BYTE PTR [rdi+1+rax], cl
lea rcx, [rax+2]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+2+rax]
mov BYTE PTR [rdi+2+rax], cl
lea rcx, [rax+3]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+3+rax]
mov BYTE PTR [rdi+3+rax], cl
lea rcx, [rax+4]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+4+rax]
mov BYTE PTR [rdi+4+rax], cl
lea rcx, [rax+5]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+5+rax]
mov BYTE PTR [rdi+5+rax], cl
lea rcx, [rax+6]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+6+rax]
mov BYTE PTR [rdi+6+rax], cl
lea rcx, [rax+7]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+7+rax]
mov BYTE PTR [rdi+7+rax], cl
lea rcx, [rax+8]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+8+rax]
mov BYTE PTR [rdi+8+rax], cl
lea rcx, [rax+9]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+9+rax]
mov BYTE PTR [rdi+9+rax], cl
lea rcx, [rax+10]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+10+rax]

437
25. SIMD 25. SIMD
mov BYTE PTR [rdi+10+rax], cl
lea rcx, [rax+11]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+11+rax]
mov BYTE PTR [rdi+11+rax], cl
lea rcx, [rax+12]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+12+rax]
mov BYTE PTR [rdi+12+rax], cl
lea rcx, [rax+13]
cmp rdx, rcx
jbe .L1
movzx ecx, BYTE PTR [rsi+13+rax]
mov BYTE PTR [rdi+13+rax], cl
lea rcx, [rax+14]
cmp rdx, rcx
jbe .L1
movzx edx, BYTE PTR [rsi+14+rax]
mov BYTE PTR [rdi+14+rax], dl
.L1:
pop rbx
pop rbp
.L41:
rep ret
.L13:
xor eax, eax
.L3:
movzx ecx, BYTE PTR [rsi+rax]
mov BYTE PTR [rdi+rax], cl
add rax, 1
cmp rax, rdx
jne .L3
rep ret
.L28:
mov eax, 14
jmp .L4
.L15:
mov eax, 1
jmp .L4
.L16:
mov eax, 2
jmp .L4
.L17:
mov eax, 3
jmp .L4
.L18:
mov eax, 4
jmp .L4
.L19:
mov eax, 5
jmp .L4
.L20:
mov eax, 6
jmp .L4
.L21:
mov eax, 7
jmp .L4
.L22:
mov eax, 8
jmp .L4
.L23:
mov eax, 9
jmp .L4
.L24:
mov eax, 10
jmp .L4
.L25:
mov eax, 11

438
25. SIMD 25. SIMD
jmp .L4
.L26:
mov eax, 12
jmp .L4
.L27:
mov eax, 13
jmp .L4

25.2. strlen() SIMD


, , SIMD- /++ -
7 . MSVC, intrin.h.
strlen()8 SIMD-, 2-2.5 -
. XMM- 16 9 .
size_t strlen_sse2(const char *str)
{
register size_t len = 0;
const char *s=str;
bool str_is_aligned=(((unsigned int)str)&0xFFFFFFF0) == (unsigned int)str;

if (str_is_aligned==false)
return strlen (str);

__m128i xmm0 = _mm_setzero_si128();


__m128i xmm1;
int mask = 0;

for (;;)
{
xmm1 = _mm_load_si128((__m128i *)s);
xmm1 = _mm_cmpeq_epi8(xmm1, xmm0);
if ((mask = _mm_movemask_epi8(xmm1)) != 0)
{
unsigned long pos;
_BitScanForward(&pos, mask);