Implemented basic support for function pointers
This commit is contained in:
@ -26,6 +26,7 @@ func (a Assembler) Finalize(dlls dll.List) ([]byte, []byte) {
|
||||
dataLabels map[string]Address
|
||||
codePointers []*Pointer
|
||||
dataPointers []*Pointer
|
||||
funcPointers []*Pointer
|
||||
dllPointers []*Pointer
|
||||
)
|
||||
|
||||
@ -293,6 +294,33 @@ func (a Assembler) Finalize(dlls dll.List) ([]byte, []byte) {
|
||||
} else {
|
||||
code = x64.StoreDynamicNumber(code, operands.Address.Base, operands.Address.OffsetRegister, operands.Address.Length, operands.Number)
|
||||
}
|
||||
case *MemoryLabel:
|
||||
start := len(code)
|
||||
|
||||
if operands.Address.OffsetRegister == math.MaxUint8 {
|
||||
code = x64.StoreNumber(code, operands.Address.Base, operands.Address.Offset, operands.Address.Length, 0b00_00_00_00)
|
||||
} else {
|
||||
code = x64.StoreDynamicNumber(code, operands.Address.Base, operands.Address.OffsetRegister, operands.Address.Length, 0b00_00_00_00)
|
||||
}
|
||||
|
||||
size := 4
|
||||
opSize := len(code) - size - start
|
||||
memLabel := x.Data.(*MemoryLabel)
|
||||
|
||||
funcPointers = append(funcPointers, &Pointer{
|
||||
Position: Address(len(code) - size),
|
||||
OpSize: uint8(opSize),
|
||||
Size: uint8(size),
|
||||
Resolve: func() Address {
|
||||
destination, exists := codeLabels[memLabel.Label]
|
||||
|
||||
if !exists {
|
||||
panic("unknown label")
|
||||
}
|
||||
|
||||
return Address(destination)
|
||||
},
|
||||
})
|
||||
case *MemoryRegister:
|
||||
if operands.Address.OffsetRegister == math.MaxUint8 {
|
||||
code = x64.StoreRegister(code, operands.Address.Base, operands.Address.Offset, operands.Address.Length, operands.Register)
|
||||
@ -397,6 +425,12 @@ restart:
|
||||
dataStart, _ := fs.Align(codeStart+Address(len(code)), config.Align)
|
||||
data, dataLabels = a.Data.Finalize()
|
||||
|
||||
for _, pointer := range funcPointers {
|
||||
address := config.BaseAddress + Address(codeStart) + pointer.Resolve()
|
||||
slice := code[pointer.Position : pointer.Position+4]
|
||||
binary.LittleEndian.PutUint32(slice, uint32(address))
|
||||
}
|
||||
|
||||
for _, pointer := range dataPointers {
|
||||
address := config.BaseAddress + Address(dataStart) + pointer.Resolve()
|
||||
slice := code[pointer.Position : pointer.Position+4]
|
||||
|
27
src/asm/MemoryLabel.go
Normal file
27
src/asm/MemoryLabel.go
Normal file
@ -0,0 +1,27 @@
|
||||
package asm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// MemoryLabel operates with a memory address and a number.
|
||||
type MemoryLabel struct {
|
||||
Address Memory
|
||||
Label string
|
||||
}
|
||||
|
||||
// String returns a human readable version.
|
||||
func (data *MemoryLabel) String() string {
|
||||
return fmt.Sprintf("%dB [%s+%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Label)
|
||||
}
|
||||
|
||||
// MemoryLabel adds an instruction with a memory address and a label.
|
||||
func (a *Assembler) MemoryLabel(mnemonic Mnemonic, address Memory, label string) {
|
||||
a.Instructions = append(a.Instructions, Instruction{
|
||||
Mnemonic: mnemonic,
|
||||
Data: &MemoryLabel{
|
||||
Address: address,
|
||||
Label: label,
|
||||
},
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user