You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 99_Appendices/D_Nasm.md
+34-29Lines changed: 34 additions & 29 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,12 +2,12 @@
2
2
3
3
## Macros
4
4
5
-
There are some cases where some assembly code is preferred/needed to do certain operations (i.e. interrupts handling).
5
+
There are some cases where writing some assembly code is preferred/needed to do certain operations (i.e. interrupts handling).
6
6
7
-
Nasm has a macro processor that supports conditional assembly, multi-level file inclusion, etc.
8
-
Macros start with the '%' symbol.
7
+
Nasm has a macro processor that supports conditional assembly, multi-level file inclusion, etc.
8
+
A macro start with the '%' symbol.
9
9
10
-
There are 2 types of macros: single line (defined with %define) and multiline defined with %macro. In this document we will se the multi-line macros.
10
+
There are two types of macros: _single line_ (defined with `%define`) and _multiline_ wrapped around `%macro` and `%endmacro`. In this paragraph we will explain the multi-line macros.
11
11
12
12
A multi-line macro is defined as follows:
13
13
@@ -19,7 +19,7 @@ A multi-line macro is defined as follows:
19
19
%endmacro
20
20
```
21
21
22
-
In order to be accessible from C the macro has a global label has to be added, so the macro above become:
22
+
A macro can be accessed from C if needed, in this case we need to add a global label to it, for example the macro above will become:
23
23
24
24
```nasm
25
25
%macro my_first_macro 1
@@ -33,16 +33,16 @@ my_first_macro_label_%1:
33
33
34
34
In the code above we can see few new things:
35
35
36
-
* First we said the the label my_first_macro_label_%1 has to be set as global, this is pretty straightforward to understand
37
-
* the %1 in the label definition, let us create different label using the first parameter passed in the macro.
36
+
* First we said the the label `my_first_macro_label_%1` has to be set as global, this is pretty straightforward to understand.
37
+
* the `%1` in the label definition, let us create different label using the first parameter passed in the macro.
38
38
39
39
So if now we add a new line with the following code:
40
40
41
41
```nasm
42
42
my_first_macro 42
43
43
```
44
44
45
-
It creates the global label: *my_first_macro_label_42*, since it is global it will be visible also from our C code (of course if the files are linked)
45
+
It creates the global label: `my_first_macro_label_42`, and since it is global it will be visible also from our C code (of course if the files are linked)
46
46
47
47
Basically defining a macro with nasm is similar to use C define statement, these special "instruction" are evaluated by nasm preprocessor, and transformed at compile time.
48
48
@@ -55,7 +55,7 @@ my_first_macro_label_42:
55
55
sub esp 42
56
56
```
57
57
58
-
## Declaring variables
58
+
## Declaring Variables
59
59
60
60
In Nasm if we want to declare a "variable" initialized we can use the following directives:
61
61
@@ -85,7 +85,7 @@ But what if we want to declare a string? Well in this case we can use a differe
85
85
string_var:
86
86
db "Hello", 10
87
87
```
88
-
What does it mean? We are simply declaring a variable (string_variable) that starts at 'H', and fill the consecutive bytes with the next letters. But what about the last number? It is just an extra byte, that represents the newline character. So what we are really storing is the string "Hello\\n"
88
+
What does it mean? We are simply declaring a variable (string_variable) that starts at 'H', and fill the consecutive bytes with the next letters. But what about the last number? It is just an extra byte, that represents the newline character. So what we are really storing is the string _"Hello\\n"_
89
89
90
90
Now what we have seen so far is valid for a variable that can be initialized with a value, but what if we don't know the value yet, but we want just to "label" it with a variable name? Well is pretty simple, we have equivalent directives for reserving memory:
91
91
@@ -110,12 +110,12 @@ quad_var:
110
110
```
111
111
112
112
One moment! What are those number after the directives? Well it's pretty simple, they indicate how many bytes/word/dword/qword we want to allocate. In the example above:
113
-
**resb 1* Is reserving one byte
114
-
**resw 2* Is reserving 2 words, and each word is 2 bytes each, in total 4 bytes
115
-
**resd 3* Is reserving 3 dwords, again a dword is 4 bytes, in total we have 12 bytes reserved
116
-
**resq 4* Is reserving... well you should know it now...
113
+
*`resb 1` Is reserving one byte
114
+
*`resw 2` Is reserving 2 words, and each word is 2 bytes each, in total 4 bytes
115
+
*`resd 3` Is reserving 3 dwords, again a dword is 4 bytes, in total we have 12 bytes reserved
116
+
*`resq 4` Is reserving... well you should know it now...
117
117
118
-
## Nasm macros from C
118
+
## Calling C from Nasm
119
119
120
120
In the asm code, if in 64bit mode, a call to *cld* is required before calling an external C function.
121
121
@@ -141,17 +141,17 @@ call my_c_function
141
141
; other magic asm stuff that we don't care of...
142
142
```
143
143
144
-
As mentioned in the multiboot chapter, argument passing from asm to C in 64 bits is little bit different from 32 bits, so the first parameter of a C function is taken from *rdi* (followed by: rsi, rdx, rcx, r8, r9, then the stack), so the *mov rdi, 42* is setting the value of *my_value* parameter to 42.
144
+
As mentioned in the multiboot chapter, argument passing from asm to C in 64 bits is little bit different from 32 bits, so the first parameter of a C function is taken from `rdi` (followed by: `rsi`, `rdx`, `rcx`, `r8`, `r9`, then the stack), so the `mov rdi, 42` is setting the value of *my_value* parameter to 42.
145
145
146
146
The output of the printf will be then:
147
147
148
148
```
149
149
My shiny function called from nasm worth: 42
150
150
```
151
151
152
-
## About sizes
152
+
## About Sizes
153
153
154
-
Variable sizes are alway important while programming, but while programming in asm even more important to understand how they works in assembly, and since there is no real type you can't rely on the variable type.
154
+
Variable sizes are always important while coding, but while coding in asm they are even more important to understand how they works in assembly, and since there is no real type you can't rely on the variable type.
155
155
156
156
The important things to know when dealing with assembly code:
157
157
@@ -161,6 +161,7 @@ The important things to know when dealing with assembly code:
161
161
mov rax, [memory_location_label]
162
162
```
163
163
is different from:
164
+
164
165
```nasm
165
166
mov eax, [memory_location_label]
166
167
```
@@ -169,10 +170,11 @@ And it could potentially lead to two different values in the register. That beca
169
170
170
171
This is kind of misleading if we usually do mostly register to memory, or value to register, value to memory, where the size is "implicit".
171
172
172
-
Probably it can be a trivial issue, but it took me couple of hours to figure it out!
173
+
_Authors Note_: Probably it can be a trivial issue, but it took me couple of hours to figure it out!
174
+
175
+
## If Statement
173
176
174
-
## If statement
175
-
Maybe there are better ways i'm unaware of, but this is a possible solution to a complex if statement, for example if we have the following if we want to translate in C:
177
+
Below an example showing a possible solution to a complex if statement. Let's assume that we have the following `if` statement in C and we want to translate in assembly:
it can be implemented in asm in something similar to:
204
+
205
+
in asm it can be rendered with the following code
206
+
203
207
```asm
204
208
cmp [var1], SOME_VALUE
205
209
je .true_branch
@@ -208,7 +212,8 @@ je .true_branch
208
212
.true_branch
209
213
jne .else_label
210
214
```
211
-
## Switch statement
215
+
216
+
## Switch Statement
212
217
213
218
The usual switch statement in C:
214
219
```C
@@ -243,11 +248,11 @@ je .value3_case
243
248
;rst of the code
244
249
```
245
250
246
-
## Data structures
251
+
## Data Structures
247
252
248
253
Every language supports accessing data as a raw array of bytes, C provides an abstraction over this in the form of structs. NASM also happens to provide us with an abstraction over raw bytes, that is similar to how C does it.
249
254
250
-
This guide will just introduce quickly how to define a basic struct,for more information and use cases is better to check the netwide assembler official documentation (see the useful links section)
255
+
This guide will just introduce quickly how to define a basic struct,for more information and use cases is better to check the netwide assembler official documentation (see the useful links section)
251
256
252
257
Let's for example assume we have the following C struct:
253
258
@@ -258,8 +263,8 @@ struct task {
258
263
};
259
264
```
260
265
261
-
How nasm render a struct is basically declaring a list of offset labels in this way we can use them to access the field starting from the struct memory location (*Authors note: yeah it is a trick...*)
262
-
To create a struct in nasm we use the `struc` and `endstruc` keywords, and the fields are defined between these them.
266
+
How nasm render a struct is basically declaring a list of offset labels, in this way we can use them to access the field starting from the struct memory location (*Authors note: yeah it is a trick...*)
267
+
To create a struct in nasm we use the `struc` and `endstruc` keywords, and the fields are defined between them.
263
268
The example above can be rendered in the following way:
This is how to access a struct, besically we add the label representing an offset to its base address.
290
-
but what if we want to create an instance of it? Well in this case we can use the macros `istruc` and `iend`, and using `at` to access the fields. For example if we want create an instance of task with the values 1 for the id field and "hello123" for the name field, we can use the following syntax:
295
+
What if we want to create an instance of it? Well in this case we can use the macros `istruc` and `iend`, and using `at` to access the fields. For example if we want create an instance of task with the values 1 for the id field and "hello123" for the name field, we can use the following syntax:
291
296
292
297
```asm
293
298
istruc task
@@ -296,7 +301,7 @@ istruc task
296
301
iend
297
302
```
298
303
299
-
In this way we have declared a struc for the first of the two examples. But again this doesn't work with the second one, because the labels are different. In that case we have to use the full label name (that means adding the prefix task):
304
+
In this way we have declared a `struc` for the first of the two examples. But again this doesn't work with the second one, because the labels are different. In that case we have to use the full label name (that means adding the prefix task):
0 commit comments