This commit is contained in:
julianb0 2019-06-13 22:20:35 +02:00
parent 1dcad85a9c
commit 4f527e21aa
No known key found for this signature in database
GPG Key ID: 9C7ACF0C053FB8A1
13 changed files with 327 additions and 130 deletions

View File

@ -16,6 +16,12 @@ DOSK = $(shell find ka -name '*.k')
vm/a.out: $(DOSK) vm/a.out: $(DOSK)
@cd ka && ../as/k-as.py dos.k 0x100000 ../vm/a.out @cd ka && ../as/k-as.py dos.k 0x100000 ../vm/a.out
.PHONY: clean
clean:
@cd vm && make clean
@rm -f vm/a.out vm/k.exe vm/stdout.txt as/instrs.lst
test: kas vm/a.out test: kas vm/a.out
@vm/k.exe vm/a.out > vm/stdout.txt @vm/k.exe vm/a.out > vm/stdout.txt
@rm -f vm/a.out @rm -f vm/a.out

View File

@ -203,7 +203,7 @@ def parse():
def parse_preproc(line): def parse_preproc(line):
global pdata global pdata
tok = line.split(' ', 2) tok = line.split(None, 2)
# preprocessor # preprocessor
if len(tok) > 1 and tok[1] == ':=': if len(tok) > 1 and tok[1] == ':=':

View File

@ -16,10 +16,29 @@ _start:
jmp .1 jmp .1
; ;
; Essential definitions ; Some definitions
; ;
CHAR_MIN := 0x80
SHRT_MIN := 0x8000
INT_MIN := 0x80000000
LONG_MIN := 0x8000000000000000
XCHAR_MIN := 0xFFFFFFFFFFFFFF80
XSHRT_MIN := 0xFFFFFFFFFFFF8000
XINT_MIN := 0xFFFFFFFF80000000
CHAR_MAX := 0x7F CHAR_MAX := 0x7F
INT_MAX := 0x7FFF SHRT_MAX := 0x7FFF
INT_MAX := 0x7FFFFFFF
LONG_MAX := 0x7FFFFFFFFFFFFFFF
BYTE_MAX := 0xFF
WORD_MAX := 0xFFFF
LWORD_MAX := 0xFFFFFFFF
QWORD_MAX := 0xFFFFFFFFFFFFFFFF
STRLEN_MAX := 0xFFFFFFFF
; ;
; Include librairies ; Include librairies

View File

@ -30,14 +30,10 @@ _itoa:
cmp ax2, 10 ; base 10 cmp ax2, 10 ; base 10
jmp.nz .conv jmp.nz .conv
cmp ax1, -9223372036854775808 ; LONG_MIN
jmp.z .min
sgn rdx, ax1 ; extract ax1 sign sgn rdx, ax1 ; extract ax1 sign
cmp rdx, -1 ; negative? cmp rdx, -1 ; negative?
not.z ax1 ; -x = ~x+1 neg.z ax1
inc.z ax1 ; need "neg" inst...
; main loop ; main loop
.conv: .conv:
@ -50,7 +46,7 @@ _itoa:
cmp rsx, 9 ; rsx > 9 ? cmp rsx, 9 ; rsx > 9 ?
jmp.a .nondec jmp.a .nondec
add rsx, 48 ; '0' add rsx, 48 ; '0'
jmp .next jmp .next
.nondec: .nondec:
@ -90,13 +86,6 @@ _itoa:
mov b[ax0+1], 0 mov b[ax0+1], 0
ret ret
.min:
mov ax1, .min10
call strcpy
ret
.min10 = "-9223372036854775808"
; ;
; wrappers ; wrappers
; ;

View File

@ -5,6 +5,10 @@
; Main function ; Main function
; ;
main: main:
call itoa_test
ret
stosb_test:
cld cld
mov rcx, 11 mov rcx, 11
mov rax, 33 mov rax, 33
@ -44,7 +48,7 @@ movzx_test:
itoa_test: itoa_test:
mov ax0, .buf mov ax0, .buf
mov ax1, -9223372036854775807 mov ax1, LONG_MIN
mov ax2, 10 mov ax2, 10
call itoa call itoa
@ -60,10 +64,6 @@ itoa_test:
mov ax0, rax mov ax0, rax
call print call print
mov rsi, 0x10
mov rdi, 8
lea rbi, b[rdi + rsi * 2 + 1]
ret ret
.buf = [32] .buf = [32]
@ -84,42 +84,55 @@ devtest:
.buf = [32] .buf = [32]
strtest: str_test:
enter
mov ax0, .msg mov ax0, .msg
call print call print
mov ax0, .buf mov ax0, .buf1
mov ax1, .msg mov ax1, .msg
mov ax2, 5 call strcpy
prn 10
mov ax0, .buf1
call print
mov ax0, .buf2
mov ax1, .msg
mov ax2, 8
call strnzcpy call strnzcpy
prn 10 prn 10
mov ax0, .buf mov ax0, .buf2
mov ax1, 10 mov ax1, 12
call print_n call print_n
mov ax0, .buf mov ax0, .msg
mov ax1, .buf1
call strcmp
mov rbx, rax
mov ax0, .buf2
mov ax1, .msg mov ax1, .msg
call strcmp call strcmp
mov rsx, rax
mov ax0, .msg
call strlen
leave
ret ret
.msg = "HelloWorld :)" .msg = "Hello World :)"
.buf = [32]
.buf1 = [32]
.buf2 = "!!!!!!!!!!!!!"
; ;
; Exit function ; Exit function
; ;
exit: exit:
enter
mov ax0, .msg mov ax0, .msg
call print call print
leave
ret ret
.msg = "Goodbye World :(\n" .msg = "Goodbye World :(\n"

View File

@ -9,44 +9,24 @@
; 1 if the first character that does not match has a greater value in str1 than in str2 ; 1 if the first character that does not match has a greater value in str1 than in str2
; -1 if the first character that does not match has a lower value in str1 than in str2 ; -1 if the first character that does not match has a lower value in str1 than in str2
; ;
strcmp: strcmp:
cmp b[ax0], b[ax1] mov ax2, STRLEN_MAX
jmp.nz .1 jmp strncmp
test b[ax0], b[ax0]
jmp.z .1
inc ax0
inc ax1
jmp strcmp
.1:
mov rax, b[ax0]
sub rax, b[ax1]
sgn rax, rax
ret
; ;
; int strncmp(const char *str1, const char *str2, int maxn) ; int strncmp(const char *str1, const char *str2, int maxn)
; ;
strncmp: strncmp:
mov rcx, ax2 mov rcx, ax2
mov.cxz rax, 0
ret.cxz
.0: cld
cmp b[ax0], b[ax1] rep.e cmpzsb ax0, ax1
jmp.nz .1
test b[ax0], b[ax0]
jmp.z .1
inc ax0
inc ax1
loop .0
.1:
mov rax, b[ax0] mov rax, b[ax0]
sub rax, b[ax1] sub rax, b[ax1]
sgn rax, rax sgn rax, rax
ret ret

View File

@ -5,34 +5,19 @@
; void strcpy(char *, const char *) ; void strcpy(char *, const char *)
; ;
strcpy: strcpy:
mov b[ax0], b[ax1] mov ax2, STRLEN_MAX
jmp strncpy
test b[ax1], b[ax1]
ret.z
inc ax0
inc ax1
jmp strcpy
; ;
; void strncpy(char *, const char *, int) ; void strncpy(char *, const char *, int)
; ;
strncpy: strncpy:
mov rcx, ax2 mov rcx, ax2
j.cxz .2 ret.cxz
dec rcx
.1: cld
mov b[ax0], b[ax1] rep.nz movsb ax0, ax1
test b[ax1], b[ax1]
ret.z
inc ax0
inc ax1
loop .1
.2:
ret ret
; ;
@ -40,20 +25,15 @@ strncpy:
; ;
strnzcpy: strnzcpy:
mov rcx, ax2 mov rcx, ax2
j.cxz .2 ret.cxz
dec rcx dec rcx
jmp.cxz .1
cld
rep.nz movsb ax0, ax1
.1: .1:
mov b[ax0], b[ax1]
test b[ax1], b[ax1]
ret.z
inc ax0
inc ax1
loop .1
.2:
mov b[ax0], 0 mov b[ax0], 0
ret ret

View File

@ -1,37 +1,22 @@
; The OS/K Team licenses this file to you under the MIT license. ; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information. ; See the LICENSE file in the project root for more information.
;
; int strlen(char *)
;
strlen:
xor rax, rax
.1:
test b[ax0], b[ax0]
ret.z
inc rax
inc ax0
jmp .1
; ;
; int strnlen(char *, int) ; int strnlen(char *, int)
; ;
strnlen: strnlen:
xor rax, rax cld
mov rcx, ax1 mov rcx, ax1
j.cxz .2 rep.nz scasb ax0, 0
dec rcx
mov rax, ax1
.1: sub rax, rcx
test b[ax0], b[ax0]
ret.z
inc rax
inc ax0
loop .1
.2:
ret ret
;
; int strlen(char *)
;
strlen:
mov ax1, STRLEN_MAX
jmp strnlen

View File

@ -408,6 +408,9 @@ stosb r rim
# %str = %str - sizeof(x) # %str = %str - sizeof(x)
# FI # FI
# #
# Preserves CF, OF and SF
# Sets ZF according to the loaded value
#
# When no parameters are given, %dest = RAX and %str = RSI # When no parameters are given, %dest = RAX and %str = RSI
# When one parameter is given, %dest = $1 and %str = RSI # When one parameter is given, %dest = $1 and %str = RSI
# When two parameters are given, %dest = $1 and %str = $2 # When two parameters are given, %dest = $1 and %str = $2
@ -460,6 +463,19 @@ cmpsb
cmpsb r cmpsb r
cmpsb r r cmpsb r r
#
# Safe compare bytes in strings (CMPZSx)
#
# Behaves precisely like CMPSx, except in the following case:
# - If both [%str1] and [%str2] are zero, clears ZF (indicating NOT EQUAL)
#
# This prevents 'rep.e cmpsb' from looping infinitely when both strings
# have the exact same content; this allows for short strcmp's
#
cmpzsb
cmpzsb r
cmpzsb r r
# #
# Move value from string to string (MOVSx) # Move value from string to string (MOVSx)
# #
@ -472,6 +488,9 @@ cmpsb r r
# %str2 = %str2 - sizeof(x) # %str2 = %str2 - sizeof(x)
# FI # FI
# #
# Preserves CF, OF and SF
# Sets ZF according to the moved value
#
# When no parameters are given, %str1 = RDI and %str2 = RSI # When no parameters are given, %str1 = RDI and %str2 = RSI
# When one parameter is given, %str1 = RDI and %str2 = $1 # When one parameter is given, %str1 = RDI and %str2 = $1
# When two parameters are given, %str1 = $1 and %str2 = $2 # When two parameters are given, %str1 = $1 and %str2 = $2

View File

@ -7,7 +7,8 @@
IMPL_START_2(sgn) IMPL_START_2(sgn)
{ {
v1 = (long)v2 < 0 ? (ulong)-1L : 1; v1 = (v2 == 0 ? 0 :
((long)v2 < 0 ? (ulong)-1L : 1));
} }
IMPL_OUT; IMPL_OUT;

View File

@ -85,6 +85,10 @@ void lods_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
} }
R(reg1) = readmem(ctx, R(reg2), len); R(reg1) = readmem(ctx, R(reg2), len);
flg = (R(reg1) == 0 ? flg|ZF : flg&~ZF);
STR_MOVE(reg2, len);
} }
IMPL_START_0(lodsb) IMPL_START_0(lodsb)
@ -113,22 +117,219 @@ IMPL_END;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
ulong reg, val;
if (p2) {
DECV(v2, p2);
reg = p1->reg;
val = v2;
}
else if (p1) {
DECV(v1, p1);
reg = RDI;
val = v1;
}
else {
reg = RDI;
val = rax;
}
ulong x = readmem(ctx, R(reg), len);
COMPARE(x, val);
STR_MOVE(reg, len);
}
IMPL_START_0(scasb) IMPL_START_0(scasb)
{ {
scas_impl(ctx, p1, p2, 1);
}
IMPL_END;
IMPL_START_0(scasw)
{
scas_impl(ctx, p1, p2, 2);
}
IMPL_END;
IMPL_START_0(scasl)
{
scas_impl(ctx, p1, p2, 4);
}
IMPL_END;
IMPL_START_0(scasq)
{
scas_impl(ctx, p1, p2, 8);
} }
IMPL_END; IMPL_END;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
void cmps_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
ulong reg1, reg2;
if (p2) {
reg1 = p1->reg;
reg2 = p2->reg;
}
else if (p1) {
reg1 = RDI;
reg2 = p1->reg;
}
else {
reg1 = RDI;
reg2 = RSI;
}
ulong x1 = readmem(ctx, R(reg1), len);
ulong x2 = readmem(ctx, R(reg2), len);
COMPARE(x1, x2);
STR_MOVE(reg1, len);
STR_MOVE(reg2, len);
}
IMPL_START_0(cmpsb) IMPL_START_0(cmpsb)
{ {
cmps_impl(ctx, p1, p2, 1);
}
IMPL_END;
IMPL_START_0(cmpsw)
{
cmps_impl(ctx, p1, p2, 2);
}
IMPL_END;
IMPL_START_0(cmpsl)
{
cmps_impl(ctx, p1, p2, 4);
}
IMPL_END;
IMPL_START_0(cmpsq)
{
cmps_impl(ctx, p1, p2, 8);
} }
IMPL_END; IMPL_END;
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
void cmpzs_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
ulong reg1, reg2;
if (p2) {
reg1 = p1->reg;
reg2 = p2->reg;
}
else if (p1) {
reg1 = RDI;
reg2 = p1->reg;
}
else {
reg1 = RDI;
reg2 = RSI;
}
ulong x1 = readmem(ctx, R(reg1), len);
ulong x2 = readmem(ctx, R(reg2), len);
COMPARE(x1, x2);
if (!x1 && !x2)
flg &= ~ZF;
STR_MOVE(reg1, len);
STR_MOVE(reg2, len);
}
IMPL_START_0(cmpzsb)
{
cmpzs_impl(ctx, p1, p2, 1);
}
IMPL_END;
IMPL_START_0(cmzpsw)
{
cmpzs_impl(ctx, p1, p2, 2);
}
IMPL_END;
IMPL_START_0(cmpzsl)
{
cmpzs_impl(ctx, p1, p2, 4);
}
IMPL_END;
IMPL_START_0(cmpzsq)
{
cmpzs_impl(ctx, p1, p2, 8);
}
IMPL_END;
//----------------------------------------------------------------------------//
void movs_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len)
{
ulong reg1, reg2;
if (p2) {
reg1 = p1->reg;
reg2 = p2->reg;
}
else if (p1) {
reg1 = RDI;
reg2 = p1->reg;
}
else {
reg1 = RDI;
reg2 = RSI;
}
ulong x = readmem(ctx, R(reg2), len);
writemem(ctx, x, R(reg1), len);
flg = (x == 0 ? flg|ZF : flg&~ZF);
STR_MOVE(reg1, len);
STR_MOVE(reg2, len);
}
IMPL_START_0(movsb) IMPL_START_0(movsb)
{ {
movs_impl(ctx, p1, p2, 1);
}
IMPL_END;
IMPL_START_0(movsw)
{
movs_impl(ctx, p1, p2, 2);
}
IMPL_END;
IMPL_START_0(movsl)
{
movs_impl(ctx, p1, p2, 4);
}
IMPL_END;
IMPL_START_0(movsq)
{
movs_impl(ctx, p1, p2, 8);
} }
IMPL_END; IMPL_END;

View File

@ -7,7 +7,7 @@
// Imperatively read the "DECD" file before reading this code // Imperatively read the "DECD" file before reading this code
// //
static void check_param_type(ctx_t *ctx, uint prm, uchar fmt) static void check_param_type(ctx_t *ctx, instr_t *in, uint prm, uchar fmt)
{ {
bool ok; bool ok;
@ -22,8 +22,8 @@ static void check_param_type(ctx_t *ctx, uint prm, uchar fmt)
if (!ok) if (!ok)
_except(ctx, E_ILL, _except(ctx, E_ILL,
"FT1 or FT2 not matching INSTR's expected parameter types: " "FT1 or FT2 not matching %s's expected parameter types: "
"fmt=0x%x prm=0x%x", fmt, prm); "fmt=0x%x prm=0x%x", in->full, fmt, prm);
} }
void decode(ctx_t *ctx) void decode(ctx_t *ctx)
@ -102,7 +102,7 @@ skip_w2:
return; return;
} }
check_param_type(ctx, in->prm1, f1); check_param_type(ctx, in, in->prm1, f1);
extract_param(ctx, &p1, f1); extract_param(ctx, &p1, f1);
// //
@ -121,7 +121,7 @@ skip_w2:
return; return;
} }
check_param_type(ctx, in->prm2, f2); check_param_type(ctx, in, in->prm2, f2);
extract_param(ctx, &p2, f2); extract_param(ctx, &p2, f2);
exec_instr(ctx, in, &p1, &p2, lock, rep, cond, pc); exec_instr(ctx, in, &p1, &p2, lock, rep, cond, pc);

View File

@ -76,10 +76,10 @@ void dump_instr(ctx_t *ctx,
log("0x%lX: ", pc); log("0x%lX: ", pc);
if (lock) if (lock)
log("lock "); log("lock");
if (rep) if (rep)
log("rep "); log(" rep");
if (cond) if (cond)
{ {
@ -95,8 +95,12 @@ void dump_instr(ctx_t *ctx,
log("%s", cond_suffixes[cond]); log("%s", cond_suffixes[cond]);
} }
if (!rep)
log("\t\t");
log("\t"); else
log("\t");
log("%s\t", in->name); log("%s\t", in->name);