WTF was I thinking before?

This commit is contained in:
Perry Kivolowitz 2024-02-28 10:47:55 -06:00
parent c020675cd7
commit 697a9c0e87
6 changed files with 190 additions and 160 deletions

View file

@ -4,9 +4,9 @@ Given:
```c ```c
struct Foo { struct Foo {
short a; short a;
char b; char b;
int c; int c;
}; };
struct Foo Bar = { 0xaaaa, 0xbb, 0xcccccccc }; struct Foo Bar = { 0xaaaa, 0xbb, 0xcccccccc };
@ -15,62 +15,68 @@ struct Foo Bar = { 0xaaaa, 0xbb, 0xcccccccc };
Here is [one](./test02_companion1.s) way of defining and accessing the struct: Here is [one](./test02_companion1.s) way of defining and accessing the struct:
```text ```text
.global main // 1 #include "apple-linux-convergence.S" // 1
.text // 2 // 2
.align 2 // 3 GLABEL main // 3
// 4 .text // 4
main: // 5 .p2align 2 // 5
str x30, [sp, 16]! // 6 // 6
// 7 MAIN // 7
ldr x0, =fmt // 8 PUSH_P x29, x30 // 8
ldr x1, =Bar // 9 mov x29, sp // 9
ldrh w2, [x1] // 10 // 10
ldrb w3, [x1, 2] // 11 LLD_ADDR x0, fmt // 11
ldr w4, [x1, 4] // 12 LLD_ADDR x1, bar // 12
bl printf // 13 ldrh w2, [x1, 0] // 13
// 14 ldrb w3, [x1, 2] // 14
ldr x30, [sp], 16 // 15 ldr w4, [x1, 4] // 15
mov w0, wzr // 16 #if defined(__APPLE__) // 16
ret // 17 PUSH_P x3, x4 // 17
// 18 PUSH_P x1, x2 // 18
.data // 19 CRT printf // 19
// 20 add sp, sp, 32 // 20
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n" // 21 #else // 21
CRT printf // 22
#endif // 23
POP_P x29, x30 // 24
mov w0, wzr // 25
ret // 26
// 27
.data // 28
// 29
fmt: .asciz "%p a: 0x%lx b: %x c: %x\n" // 30
bar: .short 0xaaaa // 31
.byte 0xbb // 32
.byte 0 // padding // 33
.word 0xcccccccc // 34
// 35
.end // 36
``` ```
It would be understandable if you don't see where the `struct` is being It would be understandable if you don't see where the structure of the
defined. That's because it isn't. Rather, the implied +0 on `line 10` and `struct` is being specified in the code. That's because it isn't.
the 2 and 4 on `lines 11` and `12` are the hard coded offsets into the Rather, focus on the 0, 2 and 4 on lines 30 through 32. These are the
`struct`. hard coded offsets of the struct's fields `a`, `b` and `c`.
[Here](./test02_companion2.s) is a second way to define a `struct`. A second way to define the offsets of the fields within a struct which
is preferable to the one above is excerpted here.
The full text of the file is located
[here](./test02_companion2.s).
```text ```text
.global main // 1 .equ foo_a, 0 // like #define
.text // 2 .equ foo_b, 2 // like #define
.align 2 // 3 .equ foo_c, 4 // like #define
// 4 ```
.equ foo_a, 0 # like #define // 5
.equ foo_b, 2 # like #define // 6 and here:
.equ foo_c, 4 # like #define // 7
// 8 ```text
main: // 9 ldrh w2, [x1, foo_a]
str x30, [sp, 16]! // 10 ldrb w3, [x1, foo_b]
// 11 ldr w4, [x1, foo_c]
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 method uses `.equ` to make the offsets into symbolic constants.
@ -78,45 +84,28 @@ This is just like using `#define` in C and C++. That is, the above is
equivalent to the following in C or C++: equivalent to the following in C or C++:
```c ```c
#define foo_a 0 #define foo_a 0
#define foo_b 2 #define foo_b 2
#define foo_c 4 #define foo_c 4
``` ```
Finally, [here](./test02_companion3.s) is a third way of defining `structs`. Finally, [here](./test02_companion3.s) is a third way of defining
`structs`. However, this method works on Linux but not on Apple. We have
not yet discovered the incantation that allows something like this on
Apple.
The salient Linux-only code is excerpted below:
```text ```text
.global main // 1 .section Foo
.text // 2 .struct 0 // a starts at 0 and goes for 2
.align 2 // 3 Foo.a: .struct Foo.a + 2 // b starts at 2 and goes for 2
// 4 Foo.b: .struct Foo.b + 2 // c starts at 4
main: // 5 Foo.c:
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
``` ```
This method has a *substantial* benefit over the previous methods. Imagine This method has a *substantial* benefit over the previous methods.
you need to insert a new field between `Foo.a` and `Foo.b`. Simply do so. Imagine you need to insert a new field between `Foo.a` and `Foo.b`.
If you're using this third method, which is based on relative offsets, the Simply do so. If you're using this third method, which is based on
assembler will do the work of adjusting the following offsets for you. relative offsets, the assembler will do the work of adjusting the
following offsets for you.

View file

@ -1,21 +0,0 @@
.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"

View file

@ -0,0 +1,15 @@
.arch armv8-a
.file "test02.c"
.text
.global Bar
.data
.align 3
.type Bar, %object
.size Bar, 8
Bar:
.hword -21846
.byte -69
.zero 1
.word -858993460
.ident "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
.section .note.GNU-stack,"",@progbits

View file

@ -1,21 +1,36 @@
.global main #include "apple-linux-convergence.S"
.text
.align 2
main: GLABEL main
str x30, [sp, 16]! .text
.p2align 2
ldr x0, =fmt MAIN
ldr x1, =Bar PUSH_P x29, x30
ldrh w2, [x1] mov x29, sp
ldrb w3, [x1, 2]
ldr w4, [x1, 4]
bl printf
ldr x30, [sp], 16 LLD_ADDR x0, fmt
mov w0, wzr LLD_ADDR x1, bar
ret ldrh w2, [x1, 0]
ldrb w3, [x1, 2]
ldr w4, [x1, 4]
#if defined(__APPLE__)
PUSH_P x3, x4
PUSH_P x1, x2
CRT printf
add sp, sp, 32
#else
CRT printf
#endif
POP_P x29, x30
mov w0, wzr
ret
.data .data
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n" fmt: .asciz "%p a: 0x%lx b: %x c: %x\n"
bar: .short 0xaaaa
.byte 0xbb
.byte 0 // padding
.word 0xcccccccc
.end

View file

@ -1,25 +1,40 @@
.global main #include "apple-linux-convergence.S"
GLABEL main
.text .text
.align 2 .p2align 2
.equ foo_a, 0 # like #define .equ foo_a, 0 // like #define
.equ foo_b, 2 # like #define .equ foo_b, 2 // like #define
.equ foo_c, 4 # like #define .equ foo_c, 4 // like #define
main: MAIN
str x30, [sp, 16]! PUSH_P x29, x30
mov x29, sp
ldr x0, =fmt LLD_ADDR x0, fmt
ldr x1, =Bar LLD_ADDR x1, bar
ldrh w2, [x1, foo_a] ldrh w2, [x1, foo_a]
ldrb w3, [x1, foo_b] ldrb w3, [x1, foo_b]
ldr w4, [x1, foo_c] ldr w4, [x1, foo_c]
bl printf #if defined(__APPLE__)
PUSH_P x3, x4
ldr x30, [sp], 16 PUSH_P x1, x2
CRT printf
add sp, sp, 32
#else
CRT printf
#endif
POP_P x29, x30
mov w0, wzr mov w0, wzr
ret ret
.data .data
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n" fmt: .asciz "%p a: 0x%lx b: %x c: %x\n"
bar: .short 0xaaaa
.byte 0xbb
.byte 0 // padding
.word 0xcccccccc
.end

View file

@ -1,27 +1,44 @@
.global main #include "apple-linux-convergence.S"
// STRUCT DEFINITION WORKS ONLY FOR LINUX
GLABEL main
.text .text
.align 2 .p2align 2
main: MAIN
str x30, [sp, 16]! PUSH_P x29, x30
mov x29, sp
ldr x0, =fmt LLD_ADDR x0, fmt
ldr x1, =Bar LLD_ADDR x1, bar
ldrh w2, [x1, Foo.a] ldrh w2, [x1, Foo.a]
ldrb w3, [x1, Foo.b] ldrb w3, [x1, Foo.b]
ldr w4, [x1, Foo.c] ldr w4, [x1, Foo.c]
bl printf #if defined(__APPLE__)
PUSH_P x3, x4
ldr x30, [sp], 16 PUSH_P x1, x2
CRT printf
add sp, sp, 32
#else
CRT printf
#endif
POP_P x29, x30
mov w0, wzr mov w0, wzr
ret ret
.section Foo .section Foo
.struct 0 // a starts at 0 and goes for 2 .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.a: .struct Foo.a + 2 // b starts at 2 and goes for 2
Foo.b: .struct Foo.b + 2 // c starts at 4 Foo.b: .struct Foo.b + 2 // c starts at 4
Foo.c: Foo.c:
.data .data
fmt: .asciz "%p a: 0x%x b: 0x%x c: 0x%x\n" fmt: .asciz "%p a: 0x%lx b: %x c: %x\n"
bar: .short 0xaaaa
.byte 0xbb
.byte 0 // padding
.word 0xcccccccc
.end