Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions assembler/asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,41 @@ func (p *Builder) Not() *Builder {
return p
}

func (p *Builder) And() *Builder {
p.writeU16(von.AND)
return p
}

func (p *Builder) Or() *Builder {
p.writeU16(von.OR)
return p
}

func (p *Builder) Xor() *Builder {
p.writeU16(von.XOR)
return p
}

func (p *Builder) ShiftLeft() *Builder {
p.writeU16(von.SHL)
return p
}

func (p *Builder) ShiftRight() *Builder {
p.writeU16(von.SHR)
return p
}

func (p *Builder) GreaterThanInt() *Builder {
p.writeU16(von.GTI)
return p
}

func (p *Builder) GreaterThanString() *Builder {
p.writeU16(von.GTS)
return p
}

func (p *Builder) Concat() *Builder {
p.writeU16(von.CONCAT)
return p
Expand Down
115 changes: 114 additions & 1 deletion assembler/asm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,119 @@ func TestInt(t *testing.T) {
}
}

func TestBitwiseAnd(t *testing.T) {
asm := New(nil)
asm.PushInt(0b1100).
PushInt(0b1010).
And()
ret := run(asm).Top(1)
if ret != int64(0b1000) { // 12 & 10 = 8
t.Fatal("TestBitwiseAnd:", ret)
}
}

func TestBitwiseOr(t *testing.T) {
asm := New(nil)
asm.PushInt(0b1100).
PushInt(0b1010).
Or()
ret := run(asm).Top(1)
if ret != int64(0b1110) { // 12 | 10 = 14
t.Fatal("TestBitwiseOr:", ret)
}
}

func TestBitwiseXor(t *testing.T) {
asm := New(nil)
asm.PushInt(0b1100).
PushInt(0b1010).
Xor()
ret := run(asm).Top(1)
if ret != int64(0b0110) { // 12 ^ 10 = 6
t.Fatal("TestBitwiseXor:", ret)
}
}

func TestShiftLeft(t *testing.T) {
asm := New(nil)
asm.PushInt(1).
PushInt(4).
ShiftLeft()
ret := run(asm).Top(1)
if ret != int64(16) { // 1 << 4 = 16
t.Fatal("TestShiftLeft:", ret)
}
}

func TestShiftRight(t *testing.T) {
asm := New(nil)
asm.PushInt(16).
PushInt(2).
ShiftRight()
ret := run(asm).Top(1)
if ret != int64(4) { // 16 >> 2 = 4
t.Fatal("TestShiftRight:", ret)
}
}

func TestShiftRightNegative(t *testing.T) {
asm := New(nil)
asm.PushInt(-1).
PushInt(1).
ShiftRight()
ret := run(asm).Top(1)
// -1 is all 1s in two's complement
// Logical shift right fills with 0s: 0x7FFFFFFFFFFFFFFF
expected := int64(0x7FFFFFFFFFFFFFFF)
if ret != expected {
t.Fatal("TestShiftRightNegative:", ret, "expected:", expected)
}
}

func TestGreaterThanInt_True(t *testing.T) {
asm := New(nil)
asm.PushInt(5).
PushInt(3).
GreaterThanInt()
ret := run(asm).Top(1)
if ret != int64(1) { // 5 > 3 = true
t.Fatal("TestGreaterThanInt_True:", ret)
}
}

func TestGreaterThanInt_False(t *testing.T) {
asm := New(nil)
asm.PushInt(3).
PushInt(5).
GreaterThanInt()
ret := run(asm).Top(1)
if ret != int64(0) { // 3 > 5 = false
t.Fatal("TestGreaterThanInt_False:", ret)
}
}

func TestGreaterThanString_True(t *testing.T) {
asm := New(nil)
asm.PushString("World").
PushString("Hello").
GreaterThanString()
ret := run(asm).Top(1)
if ret != int64(1) { // "World" > "Hello" = true
t.Fatal("TestGreaterThanString_True:", ret)
}
}

func TestGreaterThanString_False(t *testing.T) {
asm := New(nil)
asm.PushString("Apple").
PushString("Banana").
GreaterThanString()
ret := run(asm).Top(1)
if ret != int64(0) { // "Apple" > "Banana" = false
t.Fatal("TestGreaterThanString_False:", ret)
}
}

func TestString(t *testing.T) {
asm := New(nil)
asm.PushString("Hello, ").
Expand Down Expand Up @@ -196,7 +309,7 @@ func TestKeyboardAndConsole(t *testing.T) {
SetArg(4). // i += 2
Jmp("loop").
Label("done").
PushString(string(con.PUTS)).
PushString(string(rune(con.PUTS))).
PushArg(1).
Concat().
PushString("\n").
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/qiniu/arch

go 1.25.5
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid Go version specified. Go versions follow the format major.minor (e.g., 1.21, 1.22, 1.23), not major.minor.patch. The version 1.25.5 doesn't exist and will cause the module to fail validation. Use a valid Go version like 1.21 or 1.23.

Suggested change
go 1.25.5
go 1.21

Fix it with Roo Code or mention @roomote and request a fix.

49 changes: 49 additions & 0 deletions von/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ const (
EQI // 等于 (arg1, arg2 int64)
EQS // 等于 (arg1, arg2 []byte)
NOT // 非 (arg1 int64)
AND // 位与 (arg1, arg2 int64)
OR // 位或 (arg1, arg2 int64)
XOR // 位异或 (arg1, arg2 int64)
SHL // 左移 (arg1, arg2 int64)
SHR // 右移 (arg1, arg2 int64) - 逻辑右移
GTI // 大于 (arg1, arg2 int64)
GTS // 大于 (arg1, arg2 []byte)
CONCAT // 字符串连接 (arg1, arg2 []byte)
INDEX // 取字符 (s []byte, index int64)
STRING // 字符转为字符串 (ch int64)
Expand Down Expand Up @@ -136,6 +143,48 @@ func (p *CPU) Run(pc int64) {
*ret = not((*ret).(int64))
pc += 2
debug("NOT:", p.stk)
case AND:
v := p.pop().(int64)
ret := p.top(1)
*ret = (*ret).(int64) & v
pc += 2
debug("AND:", p.stk)
case OR:
v := p.pop().(int64)
ret := p.top(1)
*ret = (*ret).(int64) | v
pc += 2
debug("OR:", p.stk)
case XOR:
v := p.pop().(int64)
ret := p.top(1)
*ret = (*ret).(int64) ^ v
pc += 2
debug("XOR:", p.stk)
case SHL:
v := p.pop().(int64)
ret := p.top(1)
*ret = (*ret).(int64) << uint(v)
pc += 2
debug("SHL:", p.stk)
case SHR:
v := p.pop().(int64)
ret := p.top(1)
*ret = int64(uint64((*ret).(int64)) >> uint(v))
pc += 2
debug("SHR:", p.stk)
case GTI:
v := p.pop().(int64)
ret := p.top(1)
*ret = fromBool((*ret).(int64) > v)
pc += 2
debug("GTI:", p.stk)
case GTS:
v := p.pop().([]byte)
ret := p.top(1)
*ret = fromBool(bytes.Compare((*ret).([]byte), v) > 0)
pc += 2
debug("GTS:", p.stk)
case CONCAT:
v := p.pop().([]byte)
ret := p.top(1)
Expand Down