mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-21 02:26:59 +08:00
added structs
This commit is contained in:
parent
535e581f05
commit
625d3deaad
7 changed files with 236 additions and 3 deletions
121
section_1/structs/defining.md
Normal file
121
section_1/structs/defining.md
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
# Section 1 / Defining `structs`
|
||||||
|
|
||||||
|
Given:
|
||||||
|
|
||||||
|
```c
|
||||||
|
struct Foo {
|
||||||
|
short a;
|
||||||
|
char b;
|
||||||
|
int c;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Foo Bar = { 0xaaaa, 0xbb, 0xcccccccc };
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is [one](./test02_companion1.s) way of defining and accessing the struct:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.global main // 1
|
||||||
|
.text // 2
|
||||||
|
.align 2 // 3
|
||||||
|
// 4
|
||||||
|
main: // 5
|
||||||
|
str x30, [sp, 16]! // 6
|
||||||
|
// 7
|
||||||
|
ldr x0, =fmt // 8
|
||||||
|
ldr x1, =Bar // 9
|
||||||
|
ldrh w2, [x1] // 10
|
||||||
|
ldrb w3, [x1, 2] // 11
|
||||||
|
ldr w4, [x1, 4] // 12
|
||||||
|
bl printf // 13
|
||||||
|
// 14
|
||||||
|
ldr x30, [sp], 16 // 15
|
||||||
|
mov w0, wzr // 16
|
||||||
|
ret // 17
|
||||||
|
// 18
|
||||||
|
.data // 19
|
||||||
|
// 20
|
||||||
|
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n" // 21
|
||||||
|
```
|
||||||
|
|
||||||
|
It would be understandable if you don't see where the `struct` is being
|
||||||
|
defined. That's because it isn't. Rather, the implied +0 on `line 10` and
|
||||||
|
the 2 and 4 on `lines 11` and `12` are the hard coded offsets into the
|
||||||
|
`struct`.
|
||||||
|
|
||||||
|
[Here](./test02_companion2.s) is a second way to define a `struct`.
|
||||||
|
|
||||||
|
```text
|
||||||
|
.global main // 1
|
||||||
|
.text // 2
|
||||||
|
.align 2 // 3
|
||||||
|
// 4
|
||||||
|
.equ foo_a, 0 # like #define // 5
|
||||||
|
.equ foo_b, 2 # like #define // 6
|
||||||
|
.equ foo_c, 4 # like #define // 7
|
||||||
|
// 8
|
||||||
|
main: // 9
|
||||||
|
str x30, [sp, 16]! // 10
|
||||||
|
// 11
|
||||||
|
ldr x0, =fmt // 12
|
||||||
|
ldr x1, =Bar // 13
|
||||||
|
ldrh w2, [x1, foo_a] // 14
|
||||||
|
ldrb w3, [x1, foo_b] // 15
|
||||||
|
ldr w4, [x1, foo_c] // 16
|
||||||
|
bl printf // 17
|
||||||
|
// 18
|
||||||
|
ldr x30, [sp], 16 // 19
|
||||||
|
mov w0, wzr // 20
|
||||||
|
ret // 21
|
||||||
|
// 22
|
||||||
|
.data // 23
|
||||||
|
// 24
|
||||||
|
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n" // 25
|
||||||
|
```
|
||||||
|
|
||||||
|
This method uses `.equ` to make the offsets into symbolic constants.
|
||||||
|
This is just like using `#define` in C and C++. That is, the above is
|
||||||
|
equivalent to the following in C or C++:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define foo_a 0
|
||||||
|
#define foo_b 2
|
||||||
|
#define foo_c 4
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, [here](./test02_companion3.s) is a third way of defining `structs`.
|
||||||
|
|
||||||
|
```text
|
||||||
|
.global main // 1
|
||||||
|
.text // 2
|
||||||
|
.align 2 // 3
|
||||||
|
// 4
|
||||||
|
main: // 5
|
||||||
|
str x30, [sp, 16]! // 6
|
||||||
|
// 7
|
||||||
|
ldr x0, =fmt // 8
|
||||||
|
ldr x1, =Bar // 9
|
||||||
|
ldrh w2, [x1, Foo.a] // 10
|
||||||
|
ldrb w3, [x1, Foo.b] // 11
|
||||||
|
ldr w4, [x1, Foo.c] // 12
|
||||||
|
bl printf // 13
|
||||||
|
// 14
|
||||||
|
ldr x30, [sp], 16 // 15
|
||||||
|
mov w0, wzr // 16
|
||||||
|
ret // 17
|
||||||
|
// 18
|
||||||
|
.section Foo // 19
|
||||||
|
.struct 0 // a starts at 0 and goes for 2 // 20
|
||||||
|
Foo.a: .struct Foo.a + 2 // b starts at 2 and goes for 2 // 21
|
||||||
|
Foo.b: .struct Foo.b + 2 // c starts at 4 // 22
|
||||||
|
Foo.c: // 23
|
||||||
|
// 24
|
||||||
|
.data // 25
|
||||||
|
// 26
|
||||||
|
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n" // 27
|
||||||
|
```
|
||||||
|
|
||||||
|
We aren't sure this method has anything to commend it over the previous
|
||||||
|
method other than it does emphasize that offsets are relative to the
|
||||||
|
data member that comes before it.
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
struct Foo {
|
struct Foo {
|
||||||
long a;
|
long a;
|
||||||
short b;
|
short b;
|
||||||
int c;
|
int c;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Foo Bar = { 0xaaaaaaaaaaaaaaaa, 0xbbbb, 0xcccccccc };
|
struct Foo Bar = { 0xaaaaaaaaaaaaaaaa, 0xbbbb, 0xcccccccc };
|
||||||
|
|
|
||||||
21
section_1/structs/test01_companion1.s
Normal file
21
section_1/structs/test01_companion1.s
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
.global main
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
main:
|
||||||
|
str x30, [sp, 16]!
|
||||||
|
|
||||||
|
ldr x0, =fmt
|
||||||
|
ldr x1, =Fee
|
||||||
|
ldr x2, [x1]
|
||||||
|
ldrh w3, [x1, 8]
|
||||||
|
ldr w4, [x1, 12]
|
||||||
|
bl printf
|
||||||
|
|
||||||
|
ldr x30, [sp], 16
|
||||||
|
mov w0, wzr
|
||||||
|
ret
|
||||||
|
|
||||||
|
.data
|
||||||
|
|
||||||
|
fmt: .asciz "%p a: 0x%lx b: %x c: %x\n"
|
||||||
21
section_1/structs/test02_companion1.s
Normal file
21
section_1/structs/test02_companion1.s
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
.global main
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
main:
|
||||||
|
str x30, [sp, 16]!
|
||||||
|
|
||||||
|
ldr x0, =fmt
|
||||||
|
ldr x1, =Bar
|
||||||
|
ldrh w2, [x1]
|
||||||
|
ldrb w3, [x1, 2]
|
||||||
|
ldr w4, [x1, 4]
|
||||||
|
bl printf
|
||||||
|
|
||||||
|
ldr x30, [sp], 16
|
||||||
|
mov w0, wzr
|
||||||
|
ret
|
||||||
|
|
||||||
|
.data
|
||||||
|
|
||||||
|
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n"
|
||||||
25
section_1/structs/test02_companion2.s
Normal file
25
section_1/structs/test02_companion2.s
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
.global main
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
.equ foo_a, 0 # like #define
|
||||||
|
.equ foo_b, 2 # like #define
|
||||||
|
.equ foo_c, 4 # like #define
|
||||||
|
|
||||||
|
main:
|
||||||
|
str x30, [sp, 16]!
|
||||||
|
|
||||||
|
ldr x0, =fmt
|
||||||
|
ldr x1, =Bar
|
||||||
|
ldrh w2, [x1, foo_a]
|
||||||
|
ldrb w3, [x1, foo_b]
|
||||||
|
ldr w4, [x1, foo_c]
|
||||||
|
bl printf
|
||||||
|
|
||||||
|
ldr x30, [sp], 16
|
||||||
|
mov w0, wzr
|
||||||
|
ret
|
||||||
|
|
||||||
|
.data
|
||||||
|
|
||||||
|
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n"
|
||||||
27
section_1/structs/test02_companion3.s
Normal file
27
section_1/structs/test02_companion3.s
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
.global main
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
main:
|
||||||
|
str x30, [sp, 16]!
|
||||||
|
|
||||||
|
ldr x0, =fmt
|
||||||
|
ldr x1, =Bar
|
||||||
|
ldrh w2, [x1, Foo.a]
|
||||||
|
ldrb w3, [x1, Foo.b]
|
||||||
|
ldr w4, [x1, Foo.c]
|
||||||
|
bl printf
|
||||||
|
|
||||||
|
ldr x30, [sp], 16
|
||||||
|
mov w0, wzr
|
||||||
|
ret
|
||||||
|
|
||||||
|
.section Foo
|
||||||
|
.struct 0 // a starts at 0 and goes for 2
|
||||||
|
Foo.a: .struct Foo.a + 2 // b starts at 2 and goes for 2
|
||||||
|
Foo.b: .struct Foo.b + 2 // c starts at 4
|
||||||
|
Foo.c:
|
||||||
|
|
||||||
|
.data
|
||||||
|
|
||||||
|
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n"
|
||||||
18
section_1/structs/using.md
Normal file
18
section_1/structs/using.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Section 1 / Using Structs
|
||||||
|
|
||||||
|
This topic has already been covered indirectly by examples provided in:
|
||||||
|
|
||||||
|
* [alignment](./alignment.md)
|
||||||
|
* and [defining](./defining.md)
|
||||||
|
|
||||||
|
To summarize using `structs`:
|
||||||
|
|
||||||
|
* All `structs` have a base address
|
||||||
|
|
||||||
|
* The base address corresponds to the beginning of the first data member
|
||||||
|
|
||||||
|
* All subsequent data members are offsets relative to the first
|
||||||
|
|
||||||
|
* In order to use a `struct` correctly, you must have first calculated the offsets of each data member
|
||||||
|
|
||||||
|
* Sometimes there will be padding between data members due to the need to align all data members on natural boundaries.
|
||||||
Loading…
Reference in a new issue