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)
@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
@vm/k.exe vm/a.out > vm/stdout.txt
@rm -f vm/a.out

View File

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

View File

@ -16,10 +16,29 @@ _start:
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
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

View File

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

View File

@ -5,6 +5,10 @@
; Main function
;
main:
call itoa_test
ret
stosb_test:
cld
mov rcx, 11
mov rax, 33
@ -44,7 +48,7 @@ movzx_test:
itoa_test:
mov ax0, .buf
mov ax1, -9223372036854775807
mov ax1, LONG_MIN
mov ax2, 10
call itoa
@ -60,10 +64,6 @@ itoa_test:
mov ax0, rax
call print
mov rsi, 0x10
mov rdi, 8
lea rbi, b[rdi + rsi * 2 + 1]
ret
.buf = [32]
@ -84,42 +84,55 @@ devtest:
.buf = [32]
strtest:
enter
str_test:
mov ax0, .msg
call print
mov ax0, .buf
mov ax0, .buf1
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
prn 10
mov ax0, .buf
mov ax1, 10
mov ax0, .buf2
mov ax1, 12
call print_n
mov ax0, .buf
mov ax0, .msg
mov ax1, .buf1
call strcmp
mov rbx, rax
mov ax0, .buf2
mov ax1, .msg
call strcmp
mov rsx, rax
mov ax0, .msg
call strlen
leave
ret
.msg = "HelloWorld :)"
.buf = [32]
.msg = "Hello World :)"
.buf1 = [32]
.buf2 = "!!!!!!!!!!!!!"
;
; Exit function
;
exit:
enter
mov ax0, .msg
call print
leave
ret
.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 lower value in str1 than in str2
;
strcmp:
cmp b[ax0], b[ax1]
jmp.nz .1
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
mov ax2, STRLEN_MAX
jmp strncmp
;
; int strncmp(const char *str1, const char *str2, int maxn)
;
strncmp:
mov rcx, ax2
mov.cxz rax, 0
ret.cxz
.0:
cmp b[ax0], b[ax1]
jmp.nz .1
cld
rep.e cmpzsb ax0, ax1
test b[ax0], b[ax0]
jmp.z .1
inc ax0
inc ax1
loop .0
.1:
mov rax, b[ax0]
sub rax, b[ax1]
sgn rax, rax
ret

View File

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

View File

@ -1,37 +1,22 @@
; The OS/K Team licenses this file to you under the MIT license.
; 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)
;
strnlen:
xor rax, rax
cld
mov rcx, ax1
j.cxz .2
dec rcx
.1:
test b[ax0], b[ax0]
ret.z
inc rax
inc ax0
loop .1
.2:
rep.nz scasb ax0, 0
mov rax, ax1
sub rax, rcx
ret
;
; int strlen(char *)
;
strlen:
mov ax1, STRLEN_MAX
jmp strnlen

View File

@ -408,6 +408,9 @@ stosb r rim
# %str = %str - sizeof(x)
# FI
#
# Preserves CF, OF and SF
# Sets ZF according to the loaded value
#
# When no parameters are given, %dest = RAX and %str = RSI
# When one parameter is given, %dest = $1 and %str = RSI
# When two parameters are given, %dest = $1 and %str = $2
@ -460,6 +463,19 @@ cmpsb
cmpsb 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)
#
@ -472,6 +488,9 @@ cmpsb r r
# %str2 = %str2 - sizeof(x)
# FI
#
# Preserves CF, OF and SF
# Sets ZF according to the moved value
#
# When no parameters are given, %str1 = RDI and %str2 = RSI
# When one parameter is given, %str1 = RDI and %str2 = $1
# When two parameters are given, %str1 = $1 and %str2 = $2

View File

@ -7,7 +7,8 @@
IMPL_START_2(sgn)
{
v1 = (long)v2 < 0 ? (ulong)-1L : 1;
v1 = (v2 == 0 ? 0 :
((long)v2 < 0 ? (ulong)-1L : 1));
}
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);
flg = (R(reg1) == 0 ? flg|ZF : flg&~ZF);
STR_MOVE(reg2, len);
}
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)
{
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;
//----------------------------------------------------------------------------//
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)
{
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;
//----------------------------------------------------------------------------//
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)
{
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;

View File

@ -7,7 +7,7 @@
// 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;
@ -22,8 +22,8 @@ static void check_param_type(ctx_t *ctx, uint prm, uchar fmt)
if (!ok)
_except(ctx, E_ILL,
"FT1 or FT2 not matching INSTR's expected parameter types: "
"fmt=0x%x prm=0x%x", fmt, prm);
"FT1 or FT2 not matching %s's expected parameter types: "
"fmt=0x%x prm=0x%x", in->full, fmt, prm);
}
void decode(ctx_t *ctx)
@ -102,7 +102,7 @@ skip_w2:
return;
}
check_param_type(ctx, in->prm1, f1);
check_param_type(ctx, in, in->prm1, f1);
extract_param(ctx, &p1, f1);
//
@ -121,7 +121,7 @@ skip_w2:
return;
}
check_param_type(ctx, in->prm2, f2);
check_param_type(ctx, in, in->prm2, f2);
extract_param(ctx, &p2, f2);
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);
if (lock)
log("lock ");
log("lock");
if (rep)
log("rep ");
log(" rep");
if (cond)
{
@ -95,8 +95,12 @@ void dump_instr(ctx_t *ctx,
log("%s", cond_suffixes[cond]);
}
if (!rep)
log("\t\t");
log("\t");
else
log("\t");
log("%s\t", in->name);