Archived
1
0

Init commit

This commit is contained in:
sweetbread 2023-06-11 03:21:00 +03:00
commit dc685b3d93
8 changed files with 700 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
*.gox
*.kex

26
example/Makefile Normal file
View File

@ -0,0 +1,26 @@
PROGRAM=example
OBJS=../syscalls.o ../runtime.go.o colors.go.o colors.gox ../kos.go.o ../kos.gox $(PROGRAM).go.o
GOFLAGS=-m32 -c -nostdlib -nostdinc -fno-stack-protector -fno-split-stack -static -fno-leading-underscore -fno-common -fno-pie -I.
GO=gccgo
ASFLAGS=-g -f elf32 -F dwarf
NASM=nasm $(ASFLAGS)
OBJCOPY=objcopy
LDFLAGS=-n -T ../static.lds -m elf_i386 --no-ld-generated-unwind-info
all: $(OBJS) link
clean:
rm -f $(OBJS) $(PROGRAM).kex
link:
ld $(LDFLAGS) -o $(PROGRAM).kex $(OBJS)
$(OBJCOPY) $(PROGRAM).kex -O binary
%.gox: %.go.o
$(OBJCOPY) -j .go_export $< $@
%.go.o: %.go
$(GO) $(GOFLAGS) -o $@ -c $<
%.o: %.asm
$(NASM) $<

20
example/colors.go Normal file
View File

@ -0,0 +1,20 @@
package colors
const(
Black = 0x000000
Gray = 0x808080
Silver = 0xc0c0c0
White = 0xffffff
Fuchsia = 0xff00ff
Purple = 0x800080
Red = 0xff0000
Maroon = 0x800000
Yellow = 0xffff00
Olive = 0x808000
Lime = 0x00ff00
Green = 0x008000
Aqua = 0x00ffff
Teal = 0x008080
Blue = 0x0000ff
Navy =0x000080
)

79
example/example.go Normal file
View File

@ -0,0 +1,79 @@
package example
import (
"colors"
"../kos"
)
const (
Btn1 = 2
Btn2 = 3
BtnExit = 1
)
type Button struct {
label string
x int
y int
id int
}
func NewButton(label string, x int, y int, id int) Button {
return Button{
label: label,
x: x,
y: y,
id: id,
}
}
func (button *Button) make() {
kos.CreateButton(button.x, button.y, len(button.label)*15, 30, button.id, colors.Blue)
kos.WriteText(button.x, button.y, 0x11000000|colors.White, button.label)
}
func RedrawAll(barPos int) {
kos.Redraw(1)
kos.Window(500, 250, 420, 200, "GoLang")
kos.DrawLine(32, 80, 150, 80, colors.Green)
kos.DrawBar(barPos, 90, 100, 30, colors.Red)
str1 := "123"
str2 := "222"
if str1 == str2 || str2 == "222" {
kos.WriteText(50,50,0,"==")
} else {
kos.WriteText(50,50,0,"!=")
}
b1 := NewButton(" <- ", 32, 128, Btn1)
b1.make()
b2 := NewButton(" -> ", 310, 128, Btn2)
b2.make()
}
func Main() {
pos := 160
for {
switch kos.Event() {
case kos.EVENT_REDRAW:
RedrawAll(pos)
case kos.EVENT_BUTTON:
switch kos.GetButtonID() {
case Btn1:
pos -= 32
RedrawAll(pos)
case Btn2:
pos += 32
RedrawAll(pos)
case BtnExit:
kos.Exit()
}
}
}
}

34
kos.go Normal file
View File

@ -0,0 +1,34 @@
package kos
const (
EVENT_NONE = 0 /* Очередь событий пуста */
EVENT_REDRAW = 1 /* Окно и его элементы должны быть перерисованы */
EVENT_KEY = 2 /* Была нажата клавиша на клавиатуре */
EVENT_BUTTON = 3 /* Была нажата кнопка мыши */
EVENT_DESKTOP = 5 /* Завершена перерисовка рабочего стола */
EVENT_MOUSE = 6 /* Обнаружена активность мыши (движение, нажатие кнопки) */
EVENT_IPC = 7 /* Уведомление о межпроцессорном взаимодействии */
EVENT_NETWORK = 8 /* Событие сети */
EVENT_DEBUG = 9 /* Событие отладочной подсистемы */
EVENT_IRQBEGIN = 16 /* Начало обработки прерывания */
)
func Sleep(ms uint32) __asm__("go.kos.Sleep");
func GetTime() uint32 __asm__("go.kos.GetTime");
func Event() int __asm__("go.kos.Event");
func GetButtonID() int __asm__("go.kos.GetButtonID");
func CreateButton(x, y, xsize, ysize, id int, color uint32) __asm__("go.kos.CreateButton");
func Exit() __asm__("go.kos.Exit");
func Redraw(id int) __asm__("go.kos.Redraw");
func Window(y, x, w, h int, title string) __asm__("go.kos.Window");
func WriteText(x, y int, color uint32, text string) __asm__("go.kos.WriteText");
func WriteText2(x, y, color1, color2 uint32) __asm__("go.kos.WriteText2");
func DrawLine(x1, y1, x2, y2 int, color uint32) uint32 __asm__("go.kos.DrawLine");
func DrawBar(x, y, xsize, ysize int, color uint32) __asm__("go.kos.DrawBar");
func DebugOutHex(value uint32) __asm__("go.kos.DebugOutHex");
func DebugOutChar(ch byte) __asm__("go.kos.DebugOutChar");
func DebugOutStr(str string) __asm__("go.kos.DebugOutStr");
//func Pointer2byteSlice(ptr uint32) *[]byte __asm__("__unsafe_get_addr");
//func Pointer2uint32(ptr interface{}) uint32 __asm__("__unsafe_get_addr");

180
runtime.go Normal file
View File

@ -0,0 +1,180 @@
package runtime
import (
"unsafe"
)
func malloc(size uint32) unsafe.Pointer __asm__("malloc");
func MemMove(dest, src []byte, n int) {
if dest == nil || src == nil {
return
}
if len(dest) < n || len(src) < n {
return
}
equal := true
for i := 0; i < n; i++ {
if dest[i] != src[i] {
equal = false
break
}
}
if equal {
return
}
for i := 0; i < n; i++ {
dest[i] = src[i]
}
}
func Memcmp(a, b []byte) int {
lenA := len(a)
lenB := len(b)
minLen := lenA
if lenB < minLen {
minLen = lenB
}
// Преобразуем срезы байтов в указатели на память
ptrA := (*int32)(unsafe.Pointer(&a[0]))
ptrB := (*int32)(unsafe.Pointer(&b[0]))
// Сравниваем по 4 байт (размер int32) за раз
for i := 0; i < minLen/4; i++ {
if *ptrA != *ptrB {
// Если найдены различающиеся байты, возвращаем результат сравнения
if *ptrA < *ptrB {
return -1
} else {
return 1
}
}
ptrA = (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(ptrA)) + unsafe.Sizeof(*ptrA)))
ptrB = (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(ptrB)) + unsafe.Sizeof(*ptrB)))
}
// Если длины срезов отличаются, возвращаем результат сравнения длин
if lenA < lenB {
return -1
} else if lenA > lenB {
return 1
}
return 0
}
func MemEqual32(a, b []byte) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a)/4; i++ {
offset := i * 4
valA := uint32(a[offset])<<24 | uint32(a[offset+1])<<16 | uint32(a[offset+2])<<8 | uint32(a[offset+3])
valB := uint32(b[offset])<<24 | uint32(b[offset+1])<<16 | uint32(b[offset+2])<<8 | uint32(b[offset+3])
if valA != valB {
return false
}
}
return true
}
func MemEqual8(dest, src []byte, n int) bool {
if len(dest) < n || len(src) < n {
return false
}
for i := 0; i < n; i++ {
if dest[i] != src[i] {
return false
}
}
return true
}
func StrEqual(a, b string) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
func ConcatStrings(strs ...string) string {
totalLen := 0
for _, str := range strs {
totalLen += len(str)
}
result := make([]byte, totalLen)
offset := 0
for _, str := range strs {
copy(result[offset:], []byte(str))
offset += len(str)
}
return string(result)
}
func SliceBytetoString(slice []byte) string {
str := ""
for _, b := range slice {
str += string(b)
}
return str
}
func IntString(n int) string {
if n == 0 {
return "0"
}
var result string
isNegative := false
if n < 0 {
isNegative = true
n = -n
}
for n > 0 {
digit := n % 10
result = string('0'+digit) + result
n /= 10
}
if isNegative {
result = "-" + result
}
return result
}
func StringToSliceByte(str string) []byte {
slice := make([]byte, len(str))
for i := 0; i < len(str); i++ {
slice[i] = str[i]
}
return slice
}
func MakeSlice(et *uint32, len, cap int) unsafe.Pointer {
return malloc(0x1000)
}

42
static.lds Normal file
View File

@ -0,0 +1,42 @@
SECTIONS
{
. = 0x00000;
.text :
{
LONG(0x554E454D);
LONG(0x31305445);
LONG(1);
LONG(start_program);
LONG(__end);
LONG(0x10000);
LONG(0x10000);
LONG(0);
LONG(0);
*(.text)
}
.eh_frame :
{
*(.eh_frame)
}
.group :
{
*(.group)
}
.data :
{
*(.data)
}
.rodata :
{
*(.rodata)
*(.rodata.*)
}
__end = .;
}

316
syscalls.asm Normal file
View File

@ -0,0 +1,316 @@
SECTION .text
global runtime.goPanicIndex
runtime.goPanicIndex:
ret
global runtime.goPanicSliceB
runtime.goPanicSliceB:
ret
global memcmp
extern go_0runtime.Memcmp
memcmp:
call go_0runtime.Memcmp
ret
global memmove
extern go_0runtime.MemMove
memmove:
call go_0runtime.MemMove
ret
global runtime.memequal32..f
extern go_0runtime.MemEqual32
runtime.memequal32..f:
call go_0runtime.MemEqual32
ret
global runtime.memequal8..f
extern go_0runtime.MemEqual8
runtime.memequal8..f:
call go_0runtime.MemEqual8
ret
global runtime.strequal..f
extern go_0runtime.StrEqual
runtime.strequal..f:
call go_0runtime.StrEqual
ret
global runtime.concatstrings
extern go_0runtime.ConcatStrings
runtime.concatstrings:
call go_0runtime.ConcatStrings
ret
global runtime.slicebytetostring
extern go_0runtime.SliceBytetoString
runtime.slicebytetostring:
call go_0runtime.SliceBytetoString
ret
global runtime.intstring
extern go_0runtime.IntString
runtime.intstring:
call go_0runtime.IntString
ret
global runtime.stringtoslicebyte
extern go_0runtime.StringToSliceByte
runtime.stringtoslicebyte:
call go_0runtime.StringToSliceByte
ret
global runtime.makeslice
extern go_0runtime.MakeSlice
runtime.makeslice:
call go_0runtime.MakeSlice
ret
global malloc
malloc:
push ebp
mov ebp, esp
mov eax, 68
mov ebx, 12
mov ecx, dword [esp + 8] ; Параметр size передается через стек
int 0x40
mov esp, ebp
pop ebp
ret ; Возвращаемое значение находится в регистре EAX
global go.kos.Sleep
global go.kos.Event
global go.kos.GetButtonID
global go.kos.CreateButton
global go.kos.Exit
global go.kos.Redraw
global go.kos.Window
global go.kos.WriteText
global go.kos.GetTime
global go.kos.DrawLine
global go.kos.DrawBar
global go.kos.DebugOutHex
global go.kos.DebugOutChar
global go.kos.DebugOutStr
global go.kos.WriteText2
go.kos.Sleep:
push ebp
mov ebp, esp
mov eax, 5
mov ebx, [ebp+8]
int 0x40
mov esp, ebp
pop ebp
ret
go.kos.Event:
mov eax, 10
int 0x40
ret
go.kos.GetButtonID:
mov eax, 17
int 0x40
test al, al
jnz .no_button
shr eax, 8
ret
.no_button:
xor eax, eax
dec eax
ret
go.kos.Exit:
mov eax, -1
int 0x40
ret
go.kos.Redraw:
push ebp
mov ebp, esp
mov eax, 12
mov ebx, [ebp+8]
int 0x40
mov esp, ebp
pop ebp
ret
go.kos.Window:
push ebp
mov ebp, esp
mov ebx, [ebp+8]
shl ebx, 16
or ebx, [ebp+16]
mov ecx, [ebp+12]
shl ecx, 16
or ecx, [ebp+20]
mov edx, 0x14
shl edx, 24
or edx, 0xFFFFFF
mov esi, 0x808899ff
mov edi, [ebp+24]
xor eax, eax
int 0x40
mov esp, ebp
pop ebp
ret
go.kos.WriteText:
push ebp
mov ebp, esp
mov eax, 4
mov ebx, [ebp+8]
shl ebx, 16
mov bx, [ebp+12]
mov ecx, [ebp+16]
mov edx, [ebp+20]
mov esi, [ebp+24]
int 0x40
mov esp, ebp
pop ebp
ret
go.kos.WriteText2:
push ebp
mov ebp, esp
mov eax, 47
mov ebx, [ebp+8]
shl ebx, 16
mov ecx, [ebp+12]
mov edx, [ebp+20]
shl edx, 16
add edx, [ebp+24]
mov esi, [ebp+28]
int 0x40
mov esp, ebp
pop ebp
ret
go.kos.DrawLine:
push ebp
mov ebp, esp
mov ebx, [ebp+8]
shl ebx, 16
mov bx, [ebp+16]
mov ecx, [ebp+12]
shl ecx, 16
mov cx, [ebp+20]
mov edx, [ebp+24]
mov eax, 38
int 0x40
mov esp, ebp
pop ebp
ret
go.kos.DrawBar:
push ebp
mov ebp, esp
mov eax, 13
mov ebx, [ebp+8]
shl ebx, 16
mov bx, [ebp+16]
mov ecx, [ebp+12]
shl ecx, 16
mov cx, [ebp+20]
mov edx, [ebp+24]
int 0x40
mov esp, ebp
pop ebp
ret
go.kos.GetTime:
mov eax, 3
int 0x40
ret
go.kos.DebugOutHex:
mov eax, [esp+4]
mov edx, 8
new_char:
rol eax, 4
movzx ecx, al
and cl, 0x0f
mov cl, [__hexdigits + ecx]
pushad
mov eax, 63
mov ebx, 1
int 0x40
popad
dec edx
jnz new_char
ret
go.kos.DebugOutChar:
mov al, [esp+4]
pushf
pushad
mov cl, al
mov eax, 63
mov ebx, 1
int 0x40
popad
popf
ret
go.kos.DebugOutStr:
mov edx, [esp+4]
mov eax, 63
mov ebx, 1
m2:
mov cl, [edx]
test cl, cl
jz m1
int 40h
inc edx
jmp m2
m1:
ret
go.kos.CreateButton:
push ebp
mov ebp, esp
mov eax, 8
mov ebx, [ebp+8]
shl ebx, 16
mov bx, [ebp+16]
mov ecx, [ebp+12]
shl ecx, 16
mov cx, [ebp+20]
mov edx, [ebp+24]
mov esi, [ebp+28]
int 0x40
mov esp, ebp
pop ebp
ret
extern go_0example.Main
global start_program
start_program:
mov eax, 68
mov ebx, 11
int 0x40
call go_0example.Main
SECTION .data
__hexdigits:
db '0123456789ABCDEF'
__test:
dd __hexdigits
dd 15