Table of Contents for
Mastering Assembly Programming

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Mastering Assembly Programming by Alexey Lyashko Published by Packt Publishing, 2017
  1. Mastering Assembly Programming
  2. Title Page
  3. Copyright
  4. Mastering Assembly Programming
  5. Credits
  6. About the Author
  7. About the Reviewer
  8. www.PacktPub.com
  9. Why subscribe?
  10. Customer Feedback
  11. Table of Contents
  12. Preface
  13. What this book covers
  14. What you need for this book
  15. Who this book is for
  16. Conventions
  17. Reader feedback
  18. Customer support
  19. Downloading the example code
  20. Errata
  21. Piracy
  22. Questions
  23. Intel Architecture
  24. Processor registers
  25. General purpose registers
  26. Accumulators
  27. Counter
  28. Stack pointer
  29. Source and destination indices
  30. Base pointer
  31. Instruction pointer
  32. Floating point registers
  33. XMM registers
  34. Segment registers and memory organization
  35. Real mode
  36. Protected mode - segmentation
  37. Protected mode - paging
  38. Long mode - paging
  39. Control registers
  40. Debug registers
  41. Debug address registers DR0 - DR3
  42. Debug control register (DR7)
  43. Debug status register (DR6)
  44. The EFlags register
  45. Bit #0 - carry flag
  46. Bit #2 - parity flag
  47. Bit #4 - adjust flag
  48. Bit #6 - zero flag
  49. Bit #7 - sign flag
  50. Bit #8 - trap flag
  51. Bit #9 - interrupt enable flag
  52. Bit #10 - direction flag
  53. Bit #11 - overflow flag
  54. Remaining bits
  55. Summary
  56. Setting Up a Development Environment
  57. Microsoft Macro Assembler
  58. Installing Microsoft Visual Studio 2017 Community
  59. Setting up the Assembly project
  60. GNU Assembler (GAS)
  61. Installing GAS
  62. Step 1 - installing GAS
  63. Step 2 - let's test
  64. Flat Assembler
  65. Installing the Flat Assembler
  66. The first FASM program
  67. Windows
  68. Linux
  69. Summary
  70. Intel Instruction Set Architecture (ISA)
  71. Assembly source template
  72. The Windows Assembly template (32-bit)
  73. The Linux Assembly template (32-bit)
  74. Data types and their definitions
  75. A debugger
  76. The instruction set summary
  77. General purpose instructions
  78. Data transfer instructions
  79. Binary Arithmetic Instructions
  80. Decimal arithmetic instructions
  81. Logical instructions
  82. Shift and rotate instructions
  83. Bit and byte instructions
  84. Execution flow transfer instructions
  85. String instructions
  86. ENTER/LEAVE
  87. Flag control instructions
  88. Miscellaneous instructions
  89. FPU instructions
  90. Extensions
  91. AES-NI
  92. SSE
  93. Example program
  94. Summary
  95. Memory Addressing Modes
  96. Addressing code
  97. Sequential addressing
  98. Direct addressing
  99. Indirect addressing
  100. RIP based addressing
  101. Addressing data
  102. Sequential addressing
  103. Direct addressing
  104. Scale, index, base, and displacement
  105. RIP addressing
  106. Far pointers
  107. Summary
  108. Parallel Data Processing
  109. SSE
  110. Registers
  111. Revisions
  112. Biorhythm calculator
  113. The idea
  114. The algorithm
  115. Data section
  116. The code
  117. Standard header
  118. The main() function
  119. Data preparation steps
  120. Calculation loop
  121. Adjustment of sine input values
  122. Computing sine
  123. Exponentiation
  124. Factorials
  125. AVX-512
  126. Summary
  127. Macro Instructions
  128. What are macro instructions?
  129. How it works
  130. Macro instructions with parameters
  131. Variadic macro instructions
  132. An introduction to calling conventions
  133. cdecl (32-bit)
  134. stdcall (32-bit)
  135. Microsoft x64 (64-bit)
  136. AMD64 (64-bit)
  137. A note on Flat Assembler's macro capabilities
  138. Macro instructions in MASM and GAS
  139. Microsoft Macro Assembler
  140. The GNU Assembler
  141. Other assembler directives (FASM Specific)
  142. The conditional assembly
  143. Repeat directives
  144. Inclusion directives
  145. The include directive
  146. File directive
  147. Summary
  148. Data Structures
  149. Arrays
  150. Simple byte arrays
  151. Arrays of words, double words, and quad words
  152. Structures
  153. Addressing structure members
  154. Arrays of structures
  155. Arrays of pointers to structures
  156. Linked lists
  157. Special cases of linked lists
  158. Stack
  159. Queue and deque
  160. Priority queues
  161. Cyclic linked list
  162. Summary for special cases of linked lists
  163. Trees
  164. A practical example
  165. Example - trivial cryptographic virtual machine
  166. Virtual machine architecture
  167. Adding support for a virtual processor to the Flat Assembler
  168. Virtual code
  169. The virtual processor
  170. Searching the tree
  171. The loop
  172. Tree balancing
  173. Sparse matrices
  174. Graphs
  175. Summary
  176. Mixing Modules Written in Assembly and Those Written in High-Level Languages
  177. Crypto Core
  178. Portability
  179. Specifying the output format
  180. Conditional declaration of code and data sections
  181. Exporting symbols
  182. Core procedures
  183. Encryption/decryption
  184. Setting the encryption/decryption parameters
  185. f_set_data_pointer
  186. f_set_data_length
  187. GetPointers()
  188. Interfacing with C/C++
  189. Static linking - Visual Studio 2017
  190. Static linking - GCC
  191. Dynamic linking
  192. Assembly and managed code
  193. Native structure versus managed structure
  194. Importing from DLL/SO and function pointers
  195. Summary
  196. Operating System Interface
  197. The rings
  198. System call
  199. System call hardware interface
  200. Direct system calls
  201. Indirect system calls
  202. Using libraries
  203. Windows
  204. Linking against object and/or library files
  205. Object file
  206. Producing the executable
  207. Importing procedures from DLL
  208. Linux
  209. Linking against object and/or library files
  210. Object file
  211. Producing the executable
  212. Dynamic linking of ELF
  213. The code
  214. Summary
  215. Patching Legacy Code
  216. The executable
  217. The issue
  218. PE files
  219. Headers
  220. Imports
  221. Gathering information
  222. Locating calls to gets()
  223. Preparing for the patch
  224. Importing fgets()
  225. Patching calls
  226. Shim code
  227. Applying the patch
  228. A complex scenario
  229. Preparing the patch
  230. Adjusting file headers
  231. Appending a new section
  232. Fixing the call instruction
  233. ELF executables
  234. LD_PRELOAD
  235. A shared object
  236. Summary
  237. Oh, Almost Forgot
  238. Protecting the code
  239. The original code
  240. The call
  241. The call obfuscation macro
  242. A bit of kernel space
  243. LKM structure
  244. LKM source
  245. .init.text
  246. .exit.text
  247. .rodata.str1.1
  248. .modinfo
  249. .gnu.linkonce.this_module
  250. __versions
  251. Testing the LKM
  252. Summary

Decimal arithmetic instructions

In about 15 years of Assembly development and reverse engineering software, I encountered these instructions exactly once, and that was in the college. However, it would be right to mention them, for a few reasons:

  • Instructions like AAM and AAD may sometimes be used as a smaller variant of multiplication and division, since they allow immediate operand. They're smaller as they allow generation of smaller code due to their encoding.
  • Sequences like AAD 0 (which is division by zero) may be used as an exception trigger in certain protection schemes.
  • Not mentioning them would be historically wrong.
Decimal arithmetic instructions are illegal on 64-bit platforms.

First of all, what is BCD? It is Binary coded decimal (BCD) and is, in fact, an attempt to ease the conversion of binary representations of numbers to their ASCII equivalent and vice versa, as well as adding the ability to perform basic arithmetic operations on decimal numbers represented in a hexadecimal form (not their hexadecimal equivalents!).

There are two types of BCD: packed and unpacked. Packed BCD represents a decimal number using nibbles of a single byte. For example, the number 12 would be represented as 0x12. Unpacked BCD, on the other hand, uses bytes for representation of individual digits (for example, 12 converts to 0x0102).

However, given the fact that these instructions have not been changed since their first appearance, they only operate on values stored in a single byte, for packed BCD, or values stored in a single word, for unpacked BCD. More than this, these values should be stored only in the AL register for packed BCD and the AX register (or, to say it in a more precise way, in the AH:AL pair) for unpacked BCD.

There are only six BCD instructions:

  • Decimal Adjust after Addition (DAA): This instruction is specific to packed BCD. Since the addition of two packed BCD numbers would not necessarily result in a valid packed BCD number, the invocation of DAA fixes the problem by making the adjustments needed for converting a result into a proper packed BCD value. For example, let's add 12 and 18. Normally, the result would be 30, but if we add 0x12 and 0x18, the result would be 0x2a. The following example illustrates the procedure for such a calculation:
mov al, 0x12   ; AL = 0x12, which is packed BCD 
; representation of 12
add al, 0x18 ; Add BCD representation of 18,
; which would result in 0x2a

daa ; Adjust. AL would contain 0x30 after this instruction,
; which is the BCD representation of 30
  • Decimal Adjust after Subtraction (DAS): This instruction performs similar adjustments after subtracting two packed BCD numbers. Let's add some more lines to the preceding code (AL still contains 0x30):

sub al, 0x03  ; We are subtracting 3 from 30, however, 
; the result of 0x30 - 0x03
; would be 0x2d
das ; This instruction sets AL to 0x27,
; which is the packed BCD

; representation of 27.
  • ASCII Adjust after Addition (AAA): This instruction is similar to DAA, yet it works on unpacked BCD numbers (meaning, the AX register). Let's look at the following example, where we still add 18 to 12, but we do that with the unpacked BCD:
mov ax, 0x0102  ; 0x0102 is the unpacked BCD representation of 12
add ax, 0x0108 ; same for 18
; The result of the addition would be
; 0x020a - far from being 0x0300

aaa ; Converts the value of AX register to 0x0300

The resulting value may easily be converted to the ASCII representation by adding 0x3030.

  • ASCII Adjust after Subtraction (AAS): This instruction is similar to DAS, but operates on unpacked BCD numbers. We may continue to add code to the preceding example (The AX register still has the value of 0x0300). Let's subtract 3, which should, at the end, give us the value of 0x0207:
sub ax, 0x0003  ; AX now contains 0x02fd
aas ; So we convert it to unpacked BCD
; representation, but...
; AX becomes 0x0107, but as we know,
; 30 - 3 != 17...

What went wrong then? In fact, nothing went wrong; it is just that the internal implementation of the AAS instruction caused carry (and, as we may see in a debugger, the CF is in deed set) or, to be more precise, a borrow occurred. That is why it is better for our convenience to finalize this with the following:

adc ah, 0  ; Adds the value of CF to AH

We end up with 0x0207, which is the unpacked BCD representation of 27--exactly the result we were expecting.

  • ASCII Adjust AX after Multiply (AAM): Result of the multiplication of two unpacked BCD numbers, as well, requires certain adjustments to be made in order to be in an unpacked BCD form. However, what we have to remember first of all is the size limitation implied by these operations. As we are limited to the AX register, the maximum value of a multiplicand is 9 (or 0x09), meaning that, being limited to AX with the resulting value, we are limited to one byte with multiplicands. Let's say we want to multiply 8 by 4 (which would be 0x08 * 0x04); naturally, the result would be 0x20 (the hexadecimal equivalent of 32), which is not even close to being an unpacked BCD represented number. The aam instruction solves this problem by converting the value of the AL register to the unpacked BCD format and stores it in AX:
mov al, 4 
mov bl, 8
mul bl ; AX becomes 0x0020
aam ; Converts the value of AX to the
; corresponding unpacked BCD form. Now the AX
; register equals to 0x0302

As we see, the multiplication of two unpacked BCD bytes results in an unpacked BCD word.

  • ASCII Adjust AX before Division (AAD): This is exactly as the name of the instruction suggests--it should adjust the value of the AX register before division. The size limitations are just the same as in AAM. The AX register still contains 0x0302 after the previous example, so let's divide it by 4:
mov bl, 4
aad ; Adjust AX. The value changes from 0x0302 to 0x0020
div bl ; Perform the division itself
; AL register contains the result - 0x08

As we see, although these instructions may seem to be somewhat convenient, there are better ways to convert numbers between their ASCII notation and their binary equivalents, not to mention the fact that regular arithmetic instructions are much more convenient to use.