Init commit
This commit is contained in:
commit
dc685b3d93
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.o
|
||||
*.gox
|
||||
*.kex
|
26
example/Makefile
Normal file
26
example/Makefile
Normal 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
20
example/colors.go
Normal 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
79
example/example.go
Normal 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
34
kos.go
Normal 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
180
runtime.go
Normal 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
42
static.lds
Normal 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
316
syscalls.asm
Normal 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
|
Reference in New Issue
Block a user