mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
vm
This commit is contained in:
parent
bdfd5ea9cf
commit
c8d899db9e
58
ka/ABI
58
ka/ABI
@ -5,9 +5,9 @@
|
||||
|
||||
1. STACK
|
||||
|
||||
Stack grows downward. 'rbp' and 'rsp' are both used.
|
||||
The lowest stack frame is marked by having 'rbp' = 0.
|
||||
There is a 128-bytes red zone below 'rsp'.
|
||||
Stack grows downward. 'ebp' and 'esp' are both used.
|
||||
The lowest stack frame is marked by having 'ebp' = 0.
|
||||
There is a 128-bytes red zone below 'esp'.
|
||||
|
||||
A function's assembly code looks like this:
|
||||
label:
|
||||
@ -22,14 +22,14 @@ A function's assembly code looks like this:
|
||||
|
||||
The above code is equivalent to (and can be substitued by) the following:
|
||||
label:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, N*8
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, N*8
|
||||
...
|
||||
...
|
||||
...
|
||||
mov rsp, rbp
|
||||
pop rbp
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
Between the 'enter' and the 'leave', the stack looks like this:
|
||||
@ -37,13 +37,13 @@ Between the 'enter' and the 'leave', the stack looks like this:
|
||||
. .
|
||||
. (caller's) .
|
||||
|---------------|
|
||||
| saved rip | rbp+8 rsp+(N*8)+16
|
||||
| saved rbp | rbp rsp+(N*8)+8
|
||||
| . | rbp-8 rsp+(N*8) \
|
||||
| . | rbp-16 rsp+(N-1)*8 |
|
||||
| saved eip | ebp+8 esp+(N*8)+16
|
||||
| saved ebp | ebp esp+(N*8)+8
|
||||
| . | ebp-8 esp+(N*8) \
|
||||
| . | ebp-16 esp+(N-1)*8 |
|
||||
| . | ... | <- local
|
||||
| . | rbp-(N-1)*8 rsp+8 | variables
|
||||
| . | rbp-(N*8) rsp |
|
||||
| . | ebp-(N-1)*8 esp+8 | variables
|
||||
| . | ebp-(N*8) esp |
|
||||
|---------------| /
|
||||
. (red zone) .
|
||||
. .
|
||||
@ -53,7 +53,7 @@ Between the 'enter' and the 'leave', the stack looks like this:
|
||||
'enter' and 'leave' can be omitted if ALL the following hold:
|
||||
the function
|
||||
- uses no local variables (on the stack)
|
||||
- never uses any function that changes 'rbp' nor 'rsp',
|
||||
- never uses any function that changes 'ebp' nor 'esp',
|
||||
aside from 'call' and 'ret'
|
||||
|
||||
You can never omit 'enter' without omitting 'leave', and vice-versa.
|
||||
@ -64,8 +64,8 @@ You can never omit 'enter' without omitting 'leave', and vice-versa.
|
||||
|
||||
No matter whether 'enter' and 'leave' were ommited or not, the following must
|
||||
hold true whenever a function is entered or exited from:
|
||||
- 'rbp' must be 8-bytes aligned
|
||||
- 'rsp' must be 8-bytes aligned
|
||||
- 'ebp' must be 8-bytes aligned
|
||||
- 'esp' must be 8-bytes aligned
|
||||
- the DF flag must be cleared
|
||||
|
||||
Aside from the DF flag, a function cannot assume anything about the state
|
||||
@ -79,41 +79,41 @@ cleans the stack.
|
||||
|
||||
Return values are passed in 'rax'. If the return value does not fit
|
||||
and require more registers, use the following registers, in that order:
|
||||
rax, rdx
|
||||
eax, edx
|
||||
|
||||
The following registers are volatile; the caller cannot assume
|
||||
that they will be left unmodified by the callee:
|
||||
rax, rbx, rcx, rdx, rsi, rdi, ax0, ax1, ax2, ax3, ax4, ax5
|
||||
eax, ebx, ecx, edx, esi, edi, ax0, ax1, ax2, ax3, ax4, ax5
|
||||
|
||||
The following registers are nonvolatile; the callee must preserve them:
|
||||
r12, r13, r14, r15, r16, r17, r18, r19, r20
|
||||
nx0, nx1, nx2, nx3, nx4, nx5, nx6, nx7, nx8
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
3. VARIADIC FUNCTIONS
|
||||
|
||||
To call a variadic function, do this:
|
||||
sub rsp, nargs * 8
|
||||
mov [rsp], arg0
|
||||
sub esp, nargs * 8
|
||||
mov [esp], arg0
|
||||
...
|
||||
...
|
||||
...
|
||||
mov [rsp+(N*8)], argN
|
||||
mov [esp+(N*8)], argN
|
||||
call variadic_func
|
||||
add rsp, nargs * 8
|
||||
add esp, nargs * 8
|
||||
|
||||
To the variadic function, argN can be accessed the following way:
|
||||
mov reg, [rbp+N*8+16]
|
||||
mov reg, [ebp+N*8+16]
|
||||
|
||||
For instance:
|
||||
mov rax, [rbp+16] ; arg0
|
||||
mov rdx, [rbp+24] ; arg1
|
||||
mov eax, [ebp+16] ; arg0
|
||||
mov edx, [ebp+24] ; arg1
|
||||
|
||||
It is recommended to use the reg+reg*imm16+imm16 memory format:
|
||||
mov rax, [rbp+rcx*8+16] ; accesses arg#rcx
|
||||
mov eax, [ebp+ecx*8+16] ; accesses arg#ecx
|
||||
|
||||
The 'va_list' type can be regarded as a pointer to the
|
||||
variadic function's rbp+16
|
||||
variadic function's ebp+16
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
|
44
ka/command.k
44
ka/command.k
@ -65,7 +65,7 @@ main:
|
||||
|
||||
; Fill .buf with user input
|
||||
scan eax
|
||||
jraxz .input_loop
|
||||
jeaxz .input_loop
|
||||
|
||||
; ESC key pressed?
|
||||
beq eax, 0x1B, .handle_EXIT
|
||||
@ -74,7 +74,7 @@ main:
|
||||
bne eax, 8, .handle_input
|
||||
|
||||
; anything to delete?
|
||||
jrcxz .input_loop ; no
|
||||
jecxz .input_loop ; no
|
||||
|
||||
; yes, delete it
|
||||
dec ecx
|
||||
@ -109,7 +109,7 @@ main:
|
||||
.extract_argv0:
|
||||
; did we read anything at all?
|
||||
; if not, just go back to waiting input
|
||||
jrcxz .print_prompt
|
||||
jecxz .print_prompt
|
||||
|
||||
; find first whitespace or null-terminator
|
||||
mov ecx, argbuf.size
|
||||
@ -121,7 +121,7 @@ main:
|
||||
|
||||
.next_space:
|
||||
mov ecx, b[esi]
|
||||
jrcxz .do_extract
|
||||
jecxz .do_extract
|
||||
|
||||
; skip spaces
|
||||
bne ecx, ' ', .not_a_space
|
||||
@ -138,7 +138,7 @@ main:
|
||||
.do_extract:
|
||||
; how much do we copy?
|
||||
sub ecx, edx, argbuf
|
||||
jrcxz .detect_builtin
|
||||
jecxz .detect_builtin
|
||||
dec ecx
|
||||
|
||||
mov edi, argbuf
|
||||
@ -156,67 +156,67 @@ main:
|
||||
|
||||
.builtin_cls = "cls"
|
||||
call strcmp, argv0, .builtin_cls
|
||||
jraxz .handle_CLS
|
||||
jeaxz .handle_CLS
|
||||
|
||||
.builtin_crash = "crash"
|
||||
call strcmp, argv0, .builtin_crash
|
||||
jraxz .handle_CRASH
|
||||
jeaxz .handle_CRASH
|
||||
|
||||
.builtin_date = "date"
|
||||
call strcmp, argv0, .builtin_date
|
||||
jraxz .handle_DATE
|
||||
jeaxz .handle_DATE
|
||||
|
||||
.builtin_dir = "dir"
|
||||
call strcmp, argv0, .builtin_dir
|
||||
jraxz .handle_DIR
|
||||
jeaxz .handle_DIR
|
||||
|
||||
.builtin_dump = "dump"
|
||||
call strcmp, argv0, .builtin_dump
|
||||
jraxz .handle_DUMP
|
||||
jeaxz .handle_DUMP
|
||||
|
||||
.builtin_echo = "echo"
|
||||
call strcmp, argv0, .builtin_echo
|
||||
jraxz .handle_ECHO
|
||||
jeaxz .handle_ECHO
|
||||
|
||||
.builtin_erase = "erase"
|
||||
call strcmp, argv0, .builtin_erase
|
||||
jraxz .handle_ERASE
|
||||
jeaxz .handle_ERASE
|
||||
|
||||
.builtin_exit = "exit"
|
||||
call strcmp, argv0, .builtin_exit
|
||||
jraxz .handle_EXIT
|
||||
jeaxz .handle_EXIT
|
||||
|
||||
.builtin_help = "help"
|
||||
call strcmp, argv0, .builtin_help
|
||||
jraxz .handle_HELP
|
||||
jeaxz .handle_HELP
|
||||
|
||||
.builtin_halt = "halt"
|
||||
call strcmp, argv0, .builtin_halt
|
||||
jraxz .handle_HALT
|
||||
jeaxz .handle_HALT
|
||||
|
||||
.builtin_make = "make"
|
||||
call strcmp, argv0, .builtin_make
|
||||
jraxz .handle_MAKE
|
||||
jeaxz .handle_MAKE
|
||||
|
||||
.builtin_print = "print"
|
||||
call strcmp, argv0, .builtin_print
|
||||
jraxz .handle_PRINT
|
||||
jeaxz .handle_PRINT
|
||||
|
||||
.builtin_prompt = "prompt"
|
||||
call strcmp, argv0, .builtin_prompt
|
||||
jraxz .handle_PROMPT
|
||||
jeaxz .handle_PROMPT
|
||||
|
||||
.builtin_remove = "remove"
|
||||
call strcmp, argv0, .builtin_remove
|
||||
jraxz .handle_REMOVE
|
||||
jeaxz .handle_REMOVE
|
||||
|
||||
.builtin_time = "time"
|
||||
call strcmp, argv0, .builtin_time
|
||||
jraxz .handle_TIME
|
||||
jeaxz .handle_TIME
|
||||
|
||||
.builtin_vers = "vers"
|
||||
call strcmp, argv0, .builtin_vers
|
||||
jraxz .handle_VERS
|
||||
jeaxz .handle_VERS
|
||||
|
||||
jmp .try_exec
|
||||
|
||||
@ -255,7 +255,7 @@ main:
|
||||
|
||||
.handle_ECHO:
|
||||
mov eax, q[argv1pos]
|
||||
jraxz .echo.end
|
||||
jeaxz .echo.end
|
||||
|
||||
call print, eax
|
||||
|
||||
|
@ -168,7 +168,7 @@ doprnt:
|
||||
call nx5
|
||||
|
||||
; did putc fail?
|
||||
jraxz .r
|
||||
jeaxz .r
|
||||
|
||||
; yes, so artificially set n=0
|
||||
nul nx3
|
||||
|
@ -35,7 +35,7 @@ ltostr:
|
||||
bne ax2, 10, .conv ; base 10
|
||||
|
||||
shr ecx, ax1, 63 ; extract ax1 sign
|
||||
jrcxz .conv
|
||||
jecxz .conv
|
||||
|
||||
neg ax1 ; NEG if negative
|
||||
|
||||
@ -63,7 +63,7 @@ ltostr:
|
||||
|
||||
; add minus flag, null-terminate and reverse
|
||||
.fini:
|
||||
jrcxz .cxz
|
||||
jecxz .cxz
|
||||
mov b[ax0], '-'
|
||||
inc ax0
|
||||
|
||||
|
@ -35,7 +35,7 @@ nprintf:
|
||||
print:
|
||||
.l:
|
||||
movzx eax, b[ax0]
|
||||
jraxz .r
|
||||
jeaxz .r
|
||||
|
||||
prn eax
|
||||
inc ax0
|
||||
@ -50,7 +50,7 @@ print:
|
||||
;
|
||||
nprint:
|
||||
mov ecx, ax1
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
prn b[ax0]
|
||||
|
@ -67,7 +67,7 @@ strtoq:
|
||||
movzx ecx, b[edx]
|
||||
|
||||
; "0x"/"0b" prefix
|
||||
jrcxz .done ; "0"
|
||||
jecxz .done ; "0"
|
||||
beq ecx, 'x', .parsed_0x
|
||||
beq ecx, 'b', .parsed_0b
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
;
|
||||
memcpy:
|
||||
mov ecx, ax2
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
sub edx, ax2, ecx
|
||||
@ -21,7 +21,7 @@ memcpy:
|
||||
;
|
||||
memzero:
|
||||
mov ecx, ax1
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
nul b[ax0]
|
||||
|
12
ka/crt/str.k
12
ka/crt/str.k
@ -30,7 +30,7 @@ strcpy:
|
||||
mov ecx, b[ax1]
|
||||
mov b[ax0], ecx
|
||||
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
inc ax0
|
||||
inc ax1
|
||||
@ -45,7 +45,7 @@ strcpy:
|
||||
;
|
||||
strncpy:
|
||||
mov ecx, ax2
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
mov b[ax0], b[ax1]
|
||||
@ -63,13 +63,13 @@ strncpy:
|
||||
;
|
||||
strnzcpy:
|
||||
mov ecx, ax2
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
mov eax, b[ax1]
|
||||
mov b[ax0], eax
|
||||
|
||||
jraxz .r
|
||||
jeaxz .r
|
||||
|
||||
inc ax0
|
||||
inc ax1
|
||||
@ -100,7 +100,7 @@ strcmp:
|
||||
|
||||
; both zero?
|
||||
add ecx, eax, edx
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
inc esi
|
||||
jmp .l
|
||||
@ -114,7 +114,7 @@ strcmp:
|
||||
;
|
||||
strncmp:
|
||||
mov ecx, ax2
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
movzx eax, b[ax0]
|
||||
|
@ -25,15 +25,15 @@ DaysInYear:
|
||||
|
||||
; divisible by 4?
|
||||
rem ecx, ax0, 4
|
||||
jrcxnz .end
|
||||
jecxnz .end
|
||||
|
||||
; divisible by 100?
|
||||
rem ecx, ax0, 100
|
||||
jrcxnz .leap
|
||||
jecxnz .leap
|
||||
|
||||
; divisible by 400?
|
||||
rem ecx, ax0, 400
|
||||
jrcxnz .end
|
||||
jecxnz .end
|
||||
|
||||
.leap:
|
||||
inc eax
|
||||
|
@ -41,7 +41,7 @@ ScreenOfDeath:
|
||||
pause
|
||||
|
||||
scan eax
|
||||
jraxz .loop
|
||||
jeaxz .loop
|
||||
|
||||
beq eax, 0x0A, DefaultTrapHandler.handle_Exit
|
||||
beq eax, 0x1B, DefaultTrapHandler.handle_Shutdown
|
||||
|
@ -42,7 +42,7 @@ DefaultTrapHandler:
|
||||
|
||||
; will be optimized with a table
|
||||
; when we have a "finished" consistent API
|
||||
jraxz .handle_Shutdown
|
||||
jeaxz .handle_Shutdown
|
||||
beq eax, Sys.Exit, .handle_Exit
|
||||
beq eax, Sys.ExecuteInFrame, .handle_EIF
|
||||
beq eax, Sys.ReadFile, .handle_ReadFile
|
||||
|
@ -31,7 +31,7 @@
|
||||
trap 0
|
||||
|
||||
.dir_list:
|
||||
jraxz .dir_end
|
||||
jeaxz .dir_end
|
||||
|
||||
mov nx3, ecx ; file size
|
||||
add nx2, ecx
|
||||
@ -78,14 +78,14 @@
|
||||
; print and decrease ecx, unless it's already 0
|
||||
prn b[esi]
|
||||
inc esi
|
||||
jrcxz .dir_print_ext.1
|
||||
jecxz .dir_print_ext.1
|
||||
|
||||
dec ecx
|
||||
jmp .dir_print_ext.1
|
||||
|
||||
.dir_print_ext.2:
|
||||
; did we print at least 4 bytes?
|
||||
jrcxz .dir_print_bytes ; yes, carry on
|
||||
jecxz .dir_print_bytes ; yes, carry on
|
||||
|
||||
.dir_pe2.l:
|
||||
prn ' '
|
||||
|
@ -44,7 +44,7 @@
|
||||
|
||||
; read anything?
|
||||
bltz ecx, .couldnt_read
|
||||
jrcxz .empty_file
|
||||
jecxz .empty_file
|
||||
|
||||
; all good, let's go
|
||||
mov eax, Sys.ExecuteInFrame
|
||||
|
@ -42,7 +42,7 @@
|
||||
trap 0
|
||||
|
||||
bltz ecx, .couldnt_read
|
||||
jrcxz .empty_file
|
||||
jecxz .empty_file
|
||||
|
||||
call nprint, FILE_LOADP, ecx
|
||||
|
||||
|
@ -29,19 +29,19 @@ size_t rfs_current_idx = 0;
|
||||
|
||||
long cpudev_getmaxidx(dev_t *dev)
|
||||
{
|
||||
R(RAX) = MAX_RFRAME_IDX;
|
||||
R(EAX) = MAX_RFRAME_IDX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_getrfusage(dev_t *dev)
|
||||
{
|
||||
R(RAX) = rfs_used;
|
||||
R(EAX) = rfs_used;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_getcuridx(dev_t *dev)
|
||||
{
|
||||
R(RAX) = rfs_current_idx;
|
||||
R(EAX) = rfs_current_idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -53,12 +53,12 @@ long cpudev_leastavail(dev_t *dev)
|
||||
{
|
||||
if (rfs[it] == NULL)
|
||||
{
|
||||
R(RAX) = it;
|
||||
R(EAX) = it;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
R(RAX) = -1;
|
||||
R(EAX) = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ long cpudev_isactive(dev_t *dev)
|
||||
{
|
||||
CHK_INDEX(R(AX0));
|
||||
|
||||
R(RAX) = (rfs[R(AX0)] != NULL);
|
||||
R(EAX) = (rfs[R(AX0)] != NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -170,11 +170,11 @@ long cpudev_loadreg(dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(R(AX0));
|
||||
|
||||
if ((ushort)R(AX1) >= NREGS || R(AX1) == RZX)
|
||||
if ((ushort)R(AX1) >= NREGS || R(AX1) == EZX)
|
||||
_except(E_UDF,
|
||||
"cpudev: register invalid or index out of range: #%u", R(AX1));
|
||||
|
||||
R(RAX) = rfs[R(AX0)][R(AX1)];
|
||||
R(EAX) = rfs[R(AX0)][R(AX1)];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -233,11 +233,11 @@ long cpudev_idtdel(dev_t *dev)
|
||||
long cpudev_idtquery(dev_t *dev)
|
||||
{
|
||||
if (R(AX0) >= IDT_SLOTS || idt[R(AX0)] == 0)
|
||||
R(RAX) = R(RDX) = 0;
|
||||
R(EAX) = R(EDX) = 0;
|
||||
|
||||
else {
|
||||
R(RAX) = 1;
|
||||
R(RDX) = idt[R(AX0)];
|
||||
R(EAX) = 1;
|
||||
R(EDX) = idt[R(AX0)];
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -41,7 +41,7 @@ long diskdev_findnext(dev_t *dev)
|
||||
|
||||
if (ent == NULL)
|
||||
{
|
||||
R(RAX) = 0;
|
||||
R(EAX) = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -51,21 +51,21 @@ long diskdev_findnext(dev_t *dev)
|
||||
break;
|
||||
}
|
||||
|
||||
R(RAX) = writestr(R(AX0), R(AX1), ent->d_name);
|
||||
R(EAX) = writestr(R(AX0), R(AX1), ent->d_name);
|
||||
|
||||
snprintf(name, NAME_MAX+4, "fs/%s", ent->d_name);
|
||||
|
||||
if (lstat(name, &st) < 0)
|
||||
{
|
||||
//perror("diskdev: couldn't stat file in directory: ");
|
||||
R(RCX) = -1;
|
||||
R(RDX) = -1;
|
||||
R(ECX) = -1;
|
||||
R(EDX) = -1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
R(RCX) = st.st_size;
|
||||
R(RDX) = !S_ISREG(st.st_mode);
|
||||
R(ECX) = st.st_size;
|
||||
R(EDX) = !S_ISREG(st.st_mode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -107,7 +107,7 @@ long diskdev_open(dev_t *dev)
|
||||
}
|
||||
|
||||
disk->table[fd] = tmp;
|
||||
R(RAX) = fd;
|
||||
R(EAX) = fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -145,7 +145,7 @@ long diskdev_create(dev_t *dev)
|
||||
}
|
||||
|
||||
close(tmp);
|
||||
R(RAX) = 0;
|
||||
R(EAX) = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -165,7 +165,7 @@ long diskdev_remove(dev_t *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
R(RAX) = 0;
|
||||
R(EAX) = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ long diskdev_read(dev_t *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
R(RAX) = ret;
|
||||
R(EAX) = ret;
|
||||
|
||||
// Xxx dedicated function & faster copy
|
||||
for (; ret; ret--, R(AX1)++, buf++)
|
||||
|
@ -5,14 +5,14 @@
|
||||
|
||||
long memdev_getmemoff(dev_t *dev)
|
||||
{
|
||||
R(RAX) = MEMOFF;
|
||||
R(EAX) = MEMOFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long memdev_getmemsize(dev_t *dev)
|
||||
{
|
||||
R(RAX) = ctx->mz;
|
||||
R(EAX) = ctx->mz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
20
vm/in/JMP
20
vm/in/JMP
@ -8,22 +8,22 @@
|
||||
#
|
||||
# Jump (JMP) instruction
|
||||
#
|
||||
# RIP = $1
|
||||
# EIP = $1
|
||||
#
|
||||
jmp 1
|
||||
|
||||
jraxz 1
|
||||
jrcxz 1
|
||||
jeaxz 1
|
||||
jecxz 1
|
||||
|
||||
jraxnz 1
|
||||
jrcxnz 1
|
||||
jeaxnz 1
|
||||
jecxnz 1
|
||||
|
||||
#
|
||||
# RCX-dependent jump (LOOP) instruction
|
||||
# ECX-dependent jump (LOOP) instruction
|
||||
#
|
||||
# IF (RCX > 0) THEN
|
||||
# RCX = RCX - 1
|
||||
# RIP = $1
|
||||
# IF (ECX > 0) THEN
|
||||
# ECX = ECX - 1
|
||||
# EIP = $1
|
||||
# FI
|
||||
#
|
||||
loop 1
|
||||
@ -32,7 +32,7 @@ loop 1
|
||||
# Conditional absolute jumps (branches) (BCH)
|
||||
#
|
||||
# IF (COND) THEN
|
||||
# RIP = $3
|
||||
# EIP = $3
|
||||
# FI
|
||||
#
|
||||
|
||||
|
28
vm/in/MEM
28
vm/in/MEM
@ -8,8 +8,8 @@
|
||||
#
|
||||
# Unconditional jump with possible return (CALL)
|
||||
#
|
||||
# PUSH(RIP)
|
||||
# JMP(RIP)
|
||||
# PUSH(EIP)
|
||||
# JMP(EIP)
|
||||
#
|
||||
call 1
|
||||
call 2
|
||||
@ -18,7 +18,7 @@ call 3
|
||||
#
|
||||
# Return to caller (RET)
|
||||
#
|
||||
# POP(RIP)
|
||||
# POP(EIP)
|
||||
#
|
||||
ret 0
|
||||
ret 1
|
||||
@ -26,9 +26,9 @@ ret 1
|
||||
#
|
||||
# Make new stack frame (ENTER)
|
||||
#
|
||||
# PUSH(RBP)
|
||||
# RBP = RSP
|
||||
# RSP = RSP - $1
|
||||
# PUSH(EBP)
|
||||
# EBP = ESP
|
||||
# ESP = ESP - $1
|
||||
#
|
||||
enter 0
|
||||
enter 1
|
||||
@ -37,16 +37,16 @@ enter 2
|
||||
#
|
||||
# Leave stack frame (LEAVE)
|
||||
#
|
||||
# RSP = RBP
|
||||
# POP(RBP)
|
||||
# ESP = EBP
|
||||
# POP(EBP)
|
||||
#
|
||||
leave 0
|
||||
|
||||
#
|
||||
# PUSH value onto stack
|
||||
#
|
||||
# RSP = RSP - 8
|
||||
# *RSP = $1
|
||||
# ESP = ESP - 8
|
||||
# *ESP = $1
|
||||
#
|
||||
push 1
|
||||
push 2
|
||||
@ -55,8 +55,8 @@ push 3
|
||||
#
|
||||
# POP value from stack
|
||||
#
|
||||
# $1 = *RSP
|
||||
# RSP = RSP + 8
|
||||
# $1 = *ESP
|
||||
# ESP = ESP + 8
|
||||
#
|
||||
pop 0
|
||||
pop 1
|
||||
@ -75,9 +75,9 @@ nul 2
|
||||
# $1 = ADDR($2)
|
||||
#
|
||||
# For instance:
|
||||
# LEA RAX, [RBX + RCX * 2 + 4]
|
||||
# LEA EAX, [EBX + ECX * 2 + 4]
|
||||
# will result in:
|
||||
# RAX = RBX + RCX * 2 + 4
|
||||
# EAX = EBX + ECX * 2 + 4
|
||||
#
|
||||
lea 2
|
||||
|
||||
|
11
vm/in/MISC
11
vm/in/MISC
@ -24,6 +24,15 @@ dump 0
|
||||
# Misc. instructions #
|
||||
#---------------------------------------------------------------------------#
|
||||
|
||||
#
|
||||
# Does strictly nothing
|
||||
# Memory operands not evaluated
|
||||
#
|
||||
nop 0
|
||||
nop 1
|
||||
nop 2
|
||||
nop 3
|
||||
|
||||
#
|
||||
# Throws #UDF ("undefined behaviour")
|
||||
#
|
||||
@ -48,7 +57,7 @@ utime 1
|
||||
ytime 0
|
||||
|
||||
#
|
||||
# Clear all GPR registers except RBP/RSP
|
||||
# Clear all GPR registers except EBP/ESP
|
||||
#
|
||||
cls 0
|
||||
|
||||
|
@ -8,8 +8,8 @@
|
||||
#
|
||||
# Scan string for a particular value (SCASx)
|
||||
#
|
||||
# WHILE RCX > 0 DO
|
||||
# RCX = RCX - 1
|
||||
# WHILE ECX > 0 DO
|
||||
# ECX = ECX - 1
|
||||
#
|
||||
# IF ([%1] == 0) OR ([%1] == $2) THEN
|
||||
# BREAK
|
||||
|
36
vm/in/jmp.c
36
vm/in/jmp.c
@ -5,20 +5,20 @@
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(jmp, 1) { R(RIP) = p1->val; return 0; }
|
||||
IMPL_START(jmp, 1) { R(EIP) = p1->val; return 0; }
|
||||
|
||||
IMPL_START(jraxz, 1) { if (!R(RAX)) R(RIP) = p1->val; return 0; }
|
||||
IMPL_START(jrcxz, 1) { if (!R(RCX)) R(RIP) = p1->val; return 0; }
|
||||
IMPL_START(jeaxz, 1) { if (!R(EAX)) R(EIP) = p1->val; return 0; }
|
||||
IMPL_START(jecxz, 1) { if (!R(ECX)) R(EIP) = p1->val; return 0; }
|
||||
|
||||
IMPL_START(jraxnz, 1) { if (R(RAX)) R(RIP) = p1->val; return 0; }
|
||||
IMPL_START(jrcxnz, 1) { if (R(RCX)) R(RIP) = p1->val; return 0; }
|
||||
IMPL_START(jeaxnz, 1) { if (R(EAX)) R(EIP) = p1->val; return 0; }
|
||||
IMPL_START(jecxnz, 1) { if (R(ECX)) R(EIP) = p1->val; return 0; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(loop, 1) {
|
||||
if (R(RCX) > 0) {
|
||||
R(RCX)--;
|
||||
R(RIP) = p1->val;
|
||||
if (R(ECX) > 0) {
|
||||
R(ECX)--;
|
||||
R(EIP) = p1->val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -27,25 +27,25 @@ IMPL_START(loop, 2) {
|
||||
SRCP(p1);
|
||||
if (p1->val > 0) {
|
||||
*r1 = p1->val-1;
|
||||
R(RIP) = p2->val;
|
||||
R(EIP) = p2->val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(bzr, 2) { SRCP(p1); if (p1->val == 0) R(RIP) = p2->val; return 0; }
|
||||
IMPL_START(bnz, 2) { SRCP(p1); if (p1->val != 0) R(RIP) = p2->val; return 0; }
|
||||
IMPL_START(bltz, 2) { SRCP(p1); if ((long)p1->val < 0) R(RIP) = p2->val; return 0; }
|
||||
IMPL_START(bzr, 2) { SRCP(p1); if (p1->val == 0) R(EIP) = p2->val; return 0; }
|
||||
IMPL_START(bnz, 2) { SRCP(p1); if (p1->val != 0) R(EIP) = p2->val; return 0; }
|
||||
IMPL_START(bltz, 2) { SRCP(p1); if ((long)p1->val < 0) R(EIP) = p2->val; return 0; }
|
||||
|
||||
IMPL_START(beq, 3) { SRCP(p1); if (p1->val == p2->val) R(RIP) = p3->val; return 0; }
|
||||
IMPL_START(bne, 3) { SRCP(p1); if (p1->val != p2->val) R(RIP) = p3->val; return 0; }
|
||||
IMPL_START(beq, 3) { SRCP(p1); if (p1->val == p2->val) R(EIP) = p3->val; return 0; }
|
||||
IMPL_START(bne, 3) { SRCP(p1); if (p1->val != p2->val) R(EIP) = p3->val; return 0; }
|
||||
|
||||
IMPL_START(blt, 3) { SRCP(p1); if ((long)p1->val < (long)p2->val) R(RIP) = p3->val; return 0; }
|
||||
IMPL_START(bltu, 3) { SRCP(p1); if (p1->val < p2->val) R(RIP) = p3->val; return 0; }
|
||||
IMPL_START(blt, 3) { SRCP(p1); if ((long)p1->val < (long)p2->val) R(EIP) = p3->val; return 0; }
|
||||
IMPL_START(bltu, 3) { SRCP(p1); if (p1->val < p2->val) R(EIP) = p3->val; return 0; }
|
||||
|
||||
IMPL_START(blte, 3) { SRCP(p1); if ((long)p1->val <= (long)p2->val) R(RIP) = p3->val; return 0; }
|
||||
IMPL_START(blteu, 3) { SRCP(p1); if (p1->val <= p2->val) R(RIP) = p3->val; return 0; }
|
||||
IMPL_START(blte, 3) { SRCP(p1); if ((long)p1->val <= (long)p2->val) R(EIP) = p3->val; return 0; }
|
||||
IMPL_START(blteu, 3) { SRCP(p1); if (p1->val <= p2->val) R(EIP) = p3->val; return 0; }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
88
vm/in/mem.c
88
vm/in/mem.c
@ -34,8 +34,8 @@ IMPL_START(push, 1)
|
||||
{
|
||||
XSRCP(p1->val, p1, zx);
|
||||
|
||||
R(RSP) -= 8;
|
||||
writemem(p1->val, R(RSP), 8);
|
||||
R(ESP) -= 8;
|
||||
writemem(p1->val, R(ESP), 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -45,9 +45,9 @@ IMPL_START(push, 2)
|
||||
XSRCP(p1->val, p1, zx);
|
||||
XSRCP(p2->val, p2, zx);
|
||||
|
||||
R(RSP) -= 16;
|
||||
writemem(p1->val, R(RSP) + 8, 8);
|
||||
writemem(p2->val, R(RSP) + 0, 8);
|
||||
R(ESP) -= 16;
|
||||
writemem(p1->val, R(ESP) + 8, 8);
|
||||
writemem(p2->val, R(ESP) + 0, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -58,10 +58,10 @@ IMPL_START(push, 3)
|
||||
XSRCP(p2->val, p2, zx);
|
||||
XSRCP(p3->val, p3, zx);
|
||||
|
||||
R(RSP) -= 24;
|
||||
writemem(p1->val, R(RSP) + 16, 8);
|
||||
writemem(p2->val, R(RSP) + 8, 8);
|
||||
writemem(p3->val, R(RSP) + 0, 8);
|
||||
R(ESP) -= 24;
|
||||
writemem(p1->val, R(ESP) + 16, 8);
|
||||
writemem(p2->val, R(ESP) + 8, 8);
|
||||
writemem(p3->val, R(ESP) + 0, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -70,23 +70,23 @@ IMPL_START(push, 3)
|
||||
|
||||
IMPL_START(pop, 0)
|
||||
{
|
||||
R(RSP) += 8;
|
||||
R(ESP) += 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(pop, 1)
|
||||
{
|
||||
*r1 = readmemzx(R(RSP), 8);
|
||||
R(RSP) += 8;
|
||||
*r1 = readmemzx(R(ESP), 8);
|
||||
R(ESP) += 8;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IMPL_START(pop, 2)
|
||||
{
|
||||
*r1 = readmemzx(R(RSP) + 0, 8);
|
||||
*r2 = readmemzx(R(RSP) + 8, 8);
|
||||
R(RSP) += 16;
|
||||
*r1 = readmemzx(R(ESP) + 0, 8);
|
||||
*r2 = readmemzx(R(ESP) + 8, 8);
|
||||
R(ESP) += 16;
|
||||
|
||||
return 2;
|
||||
}
|
||||
@ -97,9 +97,9 @@ IMPL_START(call, 1)
|
||||
{
|
||||
SRCP(p1);
|
||||
|
||||
R(RSP) -= 8;
|
||||
writemem(R(RIP), R(RSP), 8);
|
||||
R(RIP) = p1->val;
|
||||
R(ESP) -= 8;
|
||||
writemem(R(EIP), R(ESP), 8);
|
||||
R(EIP) = p1->val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -109,10 +109,10 @@ IMPL_START(call, 2)
|
||||
SRCP(p1);
|
||||
SRCP(p2);
|
||||
|
||||
R(RSP) -= 8;
|
||||
writemem(R(RIP), R(RSP), 8);
|
||||
R(ESP) -= 8;
|
||||
writemem(R(EIP), R(ESP), 8);
|
||||
|
||||
R(RIP) = p1->val;
|
||||
R(EIP) = p1->val;
|
||||
R(AX0) = p2->val;
|
||||
|
||||
return 0;
|
||||
@ -124,10 +124,10 @@ IMPL_START(call, 3)
|
||||
SRCP(p2);
|
||||
SRCP(p3);
|
||||
|
||||
R(RSP) -= 8;
|
||||
writemem(R(RIP), R(RSP), 8);
|
||||
R(ESP) -= 8;
|
||||
writemem(R(EIP), R(ESP), 8);
|
||||
|
||||
R(RIP) = p1->val;
|
||||
R(EIP) = p1->val;
|
||||
R(AX0) = p2->val;
|
||||
R(AX1) = p3->val;
|
||||
|
||||
@ -138,16 +138,16 @@ IMPL_START(call, 3)
|
||||
|
||||
IMPL_START(ret, 0)
|
||||
{
|
||||
R(RIP) = readmemzx(R(RSP), 8);
|
||||
R(RSP) += 8;
|
||||
R(EIP) = readmemzx(R(ESP), 8);
|
||||
R(ESP) += 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(ret, 1)
|
||||
{
|
||||
R(RIP) = readmemzx(R(RSP), 8);
|
||||
R(RSP) += 8 + (p1->val * 8);
|
||||
R(EIP) = readmemzx(R(ESP), 8);
|
||||
R(ESP) += 8 + (p1->val * 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -156,18 +156,18 @@ IMPL_START(ret, 1)
|
||||
|
||||
IMPL_START(enter, 0)
|
||||
{
|
||||
R(RSP) -= 8;
|
||||
writemem(R(RBP), R(RSP), 8);
|
||||
R(RBP) = R(RSP);
|
||||
R(ESP) -= 8;
|
||||
writemem(R(EBP), R(ESP), 8);
|
||||
R(EBP) = R(ESP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(enter, 1)
|
||||
{
|
||||
writemem(R(RBP), R(RSP) - 8, 8);
|
||||
R(RBP) = R(RSP) - 8;
|
||||
R(RSP) -= (p1->val + 1) * 8;
|
||||
writemem(R(EBP), R(ESP) - 8, 8);
|
||||
R(EBP) = R(ESP) - 8;
|
||||
R(ESP) -= (p1->val + 1) * 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -176,27 +176,27 @@ IMPL_START(enter, 2)
|
||||
{
|
||||
int i, tmp;
|
||||
|
||||
R(RSP) -= 8;
|
||||
tmp = R(RSP);
|
||||
writemem(R(RBP), R(RSP), 8);
|
||||
R(ESP) -= 8;
|
||||
tmp = R(ESP);
|
||||
writemem(R(EBP), R(ESP), 8);
|
||||
|
||||
for (i = 0; i < p2->val; i++)
|
||||
{
|
||||
R(RBP) -= 8;
|
||||
R(RSP) -= 8;
|
||||
writemem(R(RBP), R(RSP), 8);
|
||||
R(EBP) -= 8;
|
||||
R(ESP) -= 8;
|
||||
writemem(R(EBP), R(ESP), 8);
|
||||
}
|
||||
|
||||
R(RBP) = tmp;
|
||||
R(RSP) = tmp - (p1->val * 8);
|
||||
R(EBP) = tmp;
|
||||
R(ESP) = tmp - (p1->val * 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPL_START(leave, 0)
|
||||
{
|
||||
R(RSP) = R(RBP) + 8;
|
||||
R(RBP) = readmemzx(R(RBP), 8);
|
||||
R(ESP) = R(EBP) + 8;
|
||||
R(EBP) = readmemzx(R(EBP), 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
13
vm/in/misc.c
13
vm/in/misc.c
@ -9,6 +9,11 @@
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START(nop, 0) { return 0; }
|
||||
IMPL_START(nop, 1) { return 0; }
|
||||
IMPL_START(nop, 2) { return 0; }
|
||||
IMPL_START(nop, 3) { return 0; }
|
||||
|
||||
IMPL_START(pause, 0) { usleep(5000); return 0; }
|
||||
IMPL_START(udf, 0) { _except(E_UDF, "UDF instruction"); }
|
||||
|
||||
@ -48,12 +53,12 @@ IMPL_START(ytime, 0)
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm = localtime(&t);
|
||||
|
||||
R(RAX) = tm->tm_sec + tm->tm_min * 60
|
||||
R(EAX) = tm->tm_sec + tm->tm_min * 60
|
||||
+ tm->tm_hour * 60 * 60
|
||||
+ tm->tm_mday * 60 * 60 * 24;
|
||||
|
||||
R(RBX) = tm->tm_mon;
|
||||
R(RCX) = tm->tm_year + 1900;
|
||||
R(EBX) = tm->tm_mon;
|
||||
R(ECX) = tm->tm_year + 1900;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -71,7 +76,7 @@ IMPL_START(utime, 1)
|
||||
|
||||
IMPL_START(cls, 0)
|
||||
{
|
||||
for (int i = RAX; i <= R20; i++) R(i) = 0;
|
||||
for (int i = EAX; i <= NX8; i++) R(i) = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ static void scas_impl(acc_t *p1, acc_t *p2, uint len)
|
||||
if (p1->type != A_REG)
|
||||
_except(E_ILL, "SCASX given a non-REG operand");
|
||||
|
||||
while (R(RCX) > 0)
|
||||
while (R(ECX) > 0)
|
||||
{
|
||||
ulong x = readmemzx(R(p1->reg), len);
|
||||
|
||||
@ -25,7 +25,7 @@ static void scas_impl(acc_t *p1, acc_t *p2, uint len)
|
||||
|
||||
R(p1->reg) += len;
|
||||
|
||||
R(RCX)--;
|
||||
R(ECX)--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,12 +46,12 @@ IMPL_START(trap, 1)
|
||||
|
||||
IMPL_START(iret, 0) {
|
||||
if (ctx->dumpsw)
|
||||
trace("\nReturning from exception #%ld\n\n", R(R13));
|
||||
trace("\nReturning from exception #%ld\n\n", R(NX1));
|
||||
|
||||
// should do more checks
|
||||
R(RIP) = R(R15);
|
||||
rfs_current_idx = R(R14);
|
||||
ctx->rf = rfs[R(R14)];
|
||||
R(EIP) = R(NX3);
|
||||
rfs_current_idx = R(NX2);
|
||||
ctx->rf = rfs[R(NX2)];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -65,10 +65,10 @@ dev_t *devctl_common(ulong idx)
|
||||
{
|
||||
dev_t *dev = devget(idx);
|
||||
|
||||
if (!dev) R(RAX) = -2;
|
||||
else if (dev->state == DEVPWOF) R(RAX) = -3;
|
||||
else if (dev->state == DEVFERR) R(RAX) = -4;
|
||||
else if (dev->state == DEVPLUG) R(RAX) = -5;
|
||||
if (!dev) R(EAX) = -2;
|
||||
else if (dev->state == DEVPWOF) R(EAX) = -3;
|
||||
else if (dev->state == DEVFERR) R(EAX) = -4;
|
||||
else if (dev->state == DEVPLUG) R(EAX) = -5;
|
||||
else return dev;
|
||||
return NULL;
|
||||
}
|
||||
@ -87,9 +87,9 @@ IMPL_START(devctl, 2)
|
||||
case 1: writestr(R(AX0), DEVLEN, dev->name); break;
|
||||
case 2: writestr(R(AX0), DEVLEN, dev->modl); break;
|
||||
case 3: writestr(R(AX0), DEVLEN, dev->vend); break;
|
||||
case 4: R(RAX) = dev->major; R(RDX) = dev->minor; break;
|
||||
case 5: R(RAX) = dev->feats; R(RDX) = dev->revis; break;
|
||||
default: R(RAX) = -6; break;
|
||||
case 4: R(EAX) = dev->major; R(EDX) = dev->minor; break;
|
||||
case 5: R(EAX) = dev->feats; R(EDX) = dev->revis; break;
|
||||
default: R(EAX) = -6; break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -103,11 +103,11 @@ IMPL_START(iocall, 2)
|
||||
dev_t *dev = devctl_common(p1->val);
|
||||
|
||||
if (dev == NULL) return 0;
|
||||
else if (p2->val >= DEVSLOTS || dev->fslots[p2->val] == NULL) R(RAX) = -6;
|
||||
else if (p2->val >= DEVSLOTS || dev->fslots[p2->val] == NULL) R(EAX) = -6;
|
||||
|
||||
else {
|
||||
rc = dev->fslots[p2->val](dev);
|
||||
if (rc < 0) { R(RAX) = rc; R(RDX) = 0; }
|
||||
if (rc < 0) { R(EAX) = rc; R(EDX) = 0; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
422
vm/ob/command.k
422
vm/ob/command.k
@ -143,21 +143,21 @@ Sys.EnterHaltMode := 0x999
|
||||
; int strnlen(char *, int)
|
||||
;
|
||||
strnlen:
|
||||
mov rcx, ax1
|
||||
mov ecx, ax1
|
||||
scasb ax0, zero
|
||||
|
||||
sub rax, ax1, rcx
|
||||
sub eax, ax1, ecx
|
||||
ret
|
||||
|
||||
;
|
||||
; int strlen(char *)
|
||||
;
|
||||
strlen:
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov rdx, rcx
|
||||
mov ecx, 0x7AFFFFFF
|
||||
mov edx, ecx
|
||||
scasb ax0, zero
|
||||
|
||||
sub rax, rdx, rcx
|
||||
sub eax, edx, ecx
|
||||
ret
|
||||
|
||||
;
|
||||
@ -165,10 +165,10 @@ strlen:
|
||||
;
|
||||
strcpy:
|
||||
.l:
|
||||
mov rcx, b[ax1]
|
||||
mov b[ax0], rcx
|
||||
mov ecx, b[ax1]
|
||||
mov b[ax0], ecx
|
||||
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
inc ax0
|
||||
inc ax1
|
||||
@ -182,8 +182,8 @@ strcpy:
|
||||
; void strncpy(char *, const char *, int)
|
||||
;
|
||||
strncpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
mov ecx, ax2
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
mov b[ax0], b[ax1]
|
||||
@ -200,14 +200,14 @@ strncpy:
|
||||
; void strnzcpy(char *, const char *, int)
|
||||
;
|
||||
strnzcpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
mov ecx, ax2
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
mov rax, b[ax1]
|
||||
mov b[ax0], rax
|
||||
mov eax, b[ax1]
|
||||
mov b[ax0], eax
|
||||
|
||||
jraxz .r
|
||||
jeaxz .r
|
||||
|
||||
inc ax0
|
||||
inc ax1
|
||||
@ -229,68 +229,68 @@ strnzcpy:
|
||||
; <0 if the first character that does not match has a lower value in str1 than in str2
|
||||
;
|
||||
strcmp:
|
||||
nul rsi
|
||||
nul esi
|
||||
.l:
|
||||
movzx rax, b[ax0+rsi]
|
||||
movzx rdx, b[ax1+rsi]
|
||||
movzx eax, b[ax0+esi]
|
||||
movzx edx, b[ax1+esi]
|
||||
|
||||
bne rax, rdx, .r
|
||||
bne eax, edx, .r
|
||||
|
||||
; both zero?
|
||||
add rcx, rax, rdx
|
||||
jrcxz .r
|
||||
add ecx, eax, edx
|
||||
jecxz .r
|
||||
|
||||
inc rsi
|
||||
inc esi
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
sub rax, rdx
|
||||
sub eax, edx
|
||||
ret
|
||||
|
||||
;
|
||||
; int strncmp(const char *str1, const char *str2, int maxn)
|
||||
;
|
||||
strncmp:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
mov ecx, ax2
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
movzx rax, b[ax0]
|
||||
movzx rdx, b[ax1]
|
||||
movzx eax, b[ax0]
|
||||
movzx edx, b[ax1]
|
||||
|
||||
bne rax, rdx, .r
|
||||
bne eax, edx, .r
|
||||
|
||||
inc ax0
|
||||
inc ax1
|
||||
loop .l
|
||||
|
||||
.r:
|
||||
sub rax, rdx
|
||||
sub eax, edx
|
||||
ret
|
||||
|
||||
;
|
||||
; char *strchrnul(const char *str, int ch)
|
||||
;
|
||||
strchrnul:
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov ecx, 0x7AFFFFFF
|
||||
scasb ax0, ax1
|
||||
|
||||
mov rax, ax0
|
||||
mov eax, ax0
|
||||
ret
|
||||
|
||||
;
|
||||
; char *strchr(const char *str, int ch)
|
||||
;
|
||||
strchr:
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov ecx, 0x7AFFFFFF
|
||||
scasb ax0, ax1
|
||||
|
||||
bnz b[ax0], .r
|
||||
nul rax
|
||||
nul eax
|
||||
ret
|
||||
|
||||
.r:
|
||||
mov rax, ax0
|
||||
mov eax, ax0
|
||||
ret
|
||||
|
||||
;
|
||||
@ -302,11 +302,11 @@ strrev:
|
||||
bzr b[ax1], .z
|
||||
|
||||
; save str's location
|
||||
mov rsi, ax1
|
||||
mov esi, ax1
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov ecx, 0x7AFFFFFF
|
||||
scasb ax1, zero
|
||||
dec ax1
|
||||
|
||||
@ -315,7 +315,7 @@ strrev:
|
||||
; and forward through buf
|
||||
mov b[ax0], b[ax1]
|
||||
|
||||
beq ax1, rsi, .r
|
||||
beq ax1, esi, .r
|
||||
|
||||
inc ax0
|
||||
dec ax1
|
||||
@ -341,7 +341,7 @@ strrev2:
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov ecx, 0x7AFFFFFF
|
||||
scasb ax1, zero
|
||||
dec ax1
|
||||
|
||||
@ -366,12 +366,12 @@ strrev2:
|
||||
; void memcpy(void *, const void *, int)
|
||||
;
|
||||
memcpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
mov ecx, ax2
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
sub rdx, ax2, rcx
|
||||
mov b[ax0+rdx], b[ax1+rdx]
|
||||
sub edx, ax2, ecx
|
||||
mov b[ax0+edx], b[ax1+edx]
|
||||
loop .l
|
||||
|
||||
.r:
|
||||
@ -381,8 +381,8 @@ memcpy:
|
||||
; void memzero(void *, int)
|
||||
;
|
||||
memzero:
|
||||
mov rcx, ax1
|
||||
jrcxz .r
|
||||
mov ecx, ax1
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
nul b[ax0]
|
||||
@ -416,22 +416,22 @@ memzero:
|
||||
; int DaysInYear(int year)
|
||||
;
|
||||
DaysInYear:
|
||||
mov rax, 365
|
||||
mov eax, 365
|
||||
|
||||
; divisible by 4?
|
||||
rem rcx, ax0, 4
|
||||
jrcxnz .end
|
||||
rem ecx, ax0, 4
|
||||
jecxnz .end
|
||||
|
||||
; divisible by 100?
|
||||
rem rcx, ax0, 100
|
||||
jrcxnz .leap
|
||||
rem ecx, ax0, 100
|
||||
jecxnz .leap
|
||||
|
||||
; divisible by 400?
|
||||
rem rcx, ax0, 400
|
||||
jrcxnz .end
|
||||
rem ecx, ax0, 400
|
||||
jecxnz .end
|
||||
|
||||
.leap:
|
||||
inc rax
|
||||
inc eax
|
||||
|
||||
.end:
|
||||
ret
|
||||
@ -442,37 +442,37 @@ DaysInYear:
|
||||
GetTimeUTC:
|
||||
ytime
|
||||
|
||||
mov rdi, .buf
|
||||
mov edi, .buf
|
||||
|
||||
; seconds
|
||||
rem rsi, rax, 60
|
||||
mov b[rdi], rsi
|
||||
rem esi, eax, 60
|
||||
mov b[edi], esi
|
||||
|
||||
; minutes
|
||||
div rsi, rax, 60
|
||||
rem rsi, 60
|
||||
mov b[rdi+1], rsi
|
||||
div esi, eax, 60
|
||||
rem esi, 60
|
||||
mov b[edi+1], esi
|
||||
|
||||
; hours
|
||||
div rsi, rax, 3600
|
||||
rem rsi, 24
|
||||
mov b[rdi+2], rsi
|
||||
div esi, eax, 3600
|
||||
rem esi, 24
|
||||
mov b[edi+2], esi
|
||||
|
||||
; month days
|
||||
div rsi, rax, 3600*24
|
||||
mov b[rdi+3], rsi
|
||||
div esi, eax, 3600*24
|
||||
mov b[edi+3], esi
|
||||
|
||||
; month
|
||||
mov b[rdi+4], rbx
|
||||
mov b[edi+4], rbx
|
||||
|
||||
; years
|
||||
mov w[rdi+6], rcx
|
||||
mov w[edi+6], ecx
|
||||
|
||||
;
|
||||
; ydays (TODO)
|
||||
;
|
||||
|
||||
mov rax, .buf
|
||||
mov eax, .buf
|
||||
ret
|
||||
|
||||
.buf = [24]
|
||||
@ -500,8 +500,8 @@ utoa:
|
||||
; void ltostr(char *buf, int num, int base, bool signed)
|
||||
;
|
||||
ltostr:
|
||||
mov rax, ax0
|
||||
nul rcx
|
||||
mov eax, ax0
|
||||
nul ecx
|
||||
|
||||
; make sure base is in [2, 32]
|
||||
bltu ax2, 2, .bad
|
||||
@ -515,8 +515,8 @@ ltostr:
|
||||
bzr ax3, .conv
|
||||
bne ax2, 10, .conv ; base 10
|
||||
|
||||
shr rcx, ax1, 63 ; extract ax1 sign
|
||||
jrcxz .conv
|
||||
shr ecx, ax1, 63 ; extract ax1 sign
|
||||
jecxz .conv
|
||||
|
||||
neg ax1 ; NEG if negative
|
||||
|
||||
@ -524,18 +524,18 @@ ltostr:
|
||||
.conv:
|
||||
bzr ax1, .fini
|
||||
|
||||
rem rdx, ax1, ax2 ; ax1 % base
|
||||
rem edx, ax1, ax2 ; ax1 % base
|
||||
|
||||
blt 9, rdx, .nondec ; rdx > 9 ?
|
||||
blt 9, edx, .nondec ; edx > 9 ?
|
||||
|
||||
add rdx, '0'
|
||||
add edx, '0'
|
||||
jmp .next
|
||||
|
||||
.nondec:
|
||||
add rdx, 55 ; 'A' - 10
|
||||
add edx, 55 ; 'A' - 10
|
||||
|
||||
.next:
|
||||
mov b[ax0], rdx
|
||||
mov b[ax0], edx
|
||||
|
||||
inc ax0
|
||||
|
||||
@ -544,14 +544,14 @@ ltostr:
|
||||
|
||||
; add minus flag, null-terminate and reverse
|
||||
.fini:
|
||||
jrcxz .cxz
|
||||
jecxz .cxz
|
||||
mov b[ax0], '-'
|
||||
inc ax0
|
||||
|
||||
.cxz:
|
||||
nul b[ax0]
|
||||
|
||||
call strrev2, rax
|
||||
call strrev2, eax
|
||||
ret
|
||||
|
||||
;
|
||||
@ -573,8 +573,8 @@ ltostr:
|
||||
;
|
||||
; int strtol(const char *str, int base)
|
||||
;
|
||||
; rax = integer extracted from str
|
||||
; rdx = pointer to first invalid byte
|
||||
; eax = integer extracted from str
|
||||
; edx = pointer to first invalid byte
|
||||
;
|
||||
strtol:
|
||||
mov ax2, 1
|
||||
@ -583,8 +583,8 @@ strtol:
|
||||
;
|
||||
; int strtoul(const char *str, int base)
|
||||
;
|
||||
; rax = integer extracted from str
|
||||
; rdx = pointer to first invalid byte
|
||||
; eax = integer extracted from str
|
||||
; edx = pointer to first invalid byte
|
||||
;
|
||||
strtoul:
|
||||
nul ax2
|
||||
@ -596,49 +596,49 @@ strtoul:
|
||||
; guesses base when 'base'=0
|
||||
;
|
||||
strtoq:
|
||||
nul rax, rsi
|
||||
mov rdx, ax0
|
||||
nul eax, esi
|
||||
mov edx, ax0
|
||||
|
||||
; make sure base is in [2, 32]
|
||||
beq ax1, 1, .bad
|
||||
bltu 36, ax1, .bad
|
||||
|
||||
; empty string?
|
||||
bzr b[rdx], .done
|
||||
bzr b[edx], .done
|
||||
|
||||
.skip_spc:
|
||||
bne b[rdx], ' ', .no_spc
|
||||
inc rdx
|
||||
bne b[edx], ' ', .no_spc
|
||||
inc edx
|
||||
jmp .skip_spc
|
||||
|
||||
.no_spc:
|
||||
; skip +
|
||||
bne b[rdx], '+', .no_plus
|
||||
inc rdx
|
||||
bne b[edx], '+', .no_plus
|
||||
inc edx
|
||||
|
||||
.no_plus:
|
||||
; unsigned?
|
||||
bzr ax2, .unsigned
|
||||
|
||||
; parse '-'
|
||||
bne b[rdx], '-', .unsigned
|
||||
inc rdx
|
||||
mov rsi, 1
|
||||
bne b[edx], '-', .unsigned
|
||||
inc edx
|
||||
mov esi, 1
|
||||
|
||||
.unsigned:
|
||||
; base 0
|
||||
bzr ax1, .base_0
|
||||
|
||||
; base prefix?
|
||||
bne b[rdx], '0', .main_loop
|
||||
bne b[edx], '0', .main_loop
|
||||
|
||||
inc rdx
|
||||
movzx rcx, b[rdx]
|
||||
inc edx
|
||||
movzx ecx, b[edx]
|
||||
|
||||
; "0x"/"0b" prefix
|
||||
jrcxz .done ; "0"
|
||||
beq rcx, 'x', .parsed_0x
|
||||
beq rcx, 'b', .parsed_0b
|
||||
jecxz .done ; "0"
|
||||
beq ecx, 'x', .parsed_0x
|
||||
beq ecx, 'b', .parsed_0b
|
||||
|
||||
; may be octal, but we don't care
|
||||
; we accept "0110101010" (despite base=2) for instance
|
||||
@ -646,40 +646,40 @@ strtoq:
|
||||
|
||||
.parsed_0x:
|
||||
; are we in base 16?
|
||||
; if not, leave rax = 0 and *rdx = 'x'
|
||||
; if not, leave eax = 0 and *edx = 'x'
|
||||
bne ax1, 16, .done
|
||||
; else
|
||||
inc rdx
|
||||
inc edx
|
||||
jmp .main_loop
|
||||
|
||||
.parsed_0b:
|
||||
; are we in base 2?
|
||||
; if not, leave rax = 0 and *rdx = 'b'
|
||||
; if not, leave eax = 0 and *edx = 'b'
|
||||
bne ax1, 2, .done
|
||||
; else
|
||||
inc rdx
|
||||
inc edx
|
||||
jmp .main_loop
|
||||
|
||||
.base_0:
|
||||
; guess base
|
||||
|
||||
beq b[rdx], '0', .b0_not10
|
||||
beq b[edx], '0', .b0_not10
|
||||
|
||||
; must be base 10
|
||||
mov ax1, 10
|
||||
jmp .main_loop
|
||||
|
||||
.b0_not10:
|
||||
inc rdx
|
||||
inc edx
|
||||
|
||||
bne b[rdx], 'x', .b0_not16
|
||||
inc rdx
|
||||
bne b[edx], 'x', .b0_not16
|
||||
inc edx
|
||||
mov ax1, 16
|
||||
jmp .main_loop
|
||||
|
||||
.b0_not16:
|
||||
bne b[rdx], 'b', .b0_not2
|
||||
inc rdx
|
||||
bne b[edx], 'b', .b0_not2
|
||||
inc edx
|
||||
mov ax1, 2
|
||||
jmp .main_loop
|
||||
|
||||
@ -688,45 +688,45 @@ strtoq:
|
||||
mov ax1, 8
|
||||
|
||||
.main_loop:
|
||||
movzx rcx, b[rdx]
|
||||
inc rdx
|
||||
movzx ecx, b[edx]
|
||||
inc edx
|
||||
|
||||
; between 0 and 9?
|
||||
bltu rcx, '0', .done
|
||||
bltu '9', rcx, .not_digit10
|
||||
bltu ecx, '0', .done
|
||||
bltu '9', ecx, .not_digit10
|
||||
|
||||
; yes
|
||||
sub rcx, '0'
|
||||
sub ecx, '0'
|
||||
jmp .next
|
||||
|
||||
.not_digit10:
|
||||
bltu rcx, 'A', .done
|
||||
bltu 'Z', rcx, .not_digitAZ
|
||||
bltu ecx, 'A', .done
|
||||
bltu 'Z', ecx, .not_digitAZ
|
||||
|
||||
sub rcx, 55 ; 'A' - 10
|
||||
sub ecx, 55 ; 'A' - 10
|
||||
jmp .next
|
||||
|
||||
.not_digitAZ:
|
||||
bltu rcx, 'a', .done
|
||||
bltu 'z', rcx, .done
|
||||
bltu ecx, 'a', .done
|
||||
bltu 'z', ecx, .done
|
||||
|
||||
sub rcx, 87 ; 'a' - 10
|
||||
sub ecx, 87 ; 'a' - 10
|
||||
jmp .next
|
||||
|
||||
.next:
|
||||
; too large for base?
|
||||
blteu ax1, rcx, .done
|
||||
blteu ax1, ecx, .done
|
||||
|
||||
mul rax, ax1
|
||||
add rax, rcx
|
||||
mul eax, ax1
|
||||
add eax, ecx
|
||||
jmp .main_loop
|
||||
|
||||
.done:
|
||||
; negative?
|
||||
bzr rsi, .r
|
||||
bzr esi, .r
|
||||
|
||||
; yes
|
||||
neg rax
|
||||
neg eax
|
||||
|
||||
.r:
|
||||
ret
|
||||
@ -743,73 +743,73 @@ strtoq:
|
||||
; int doprnt(PUTC putc, int n, const char *fmt, va_list ap)
|
||||
;
|
||||
doprnt:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
push r12, r13, r14
|
||||
push r15, r16, r17
|
||||
push nx0, nx1, nx2
|
||||
push nx3, nx4, nx5
|
||||
|
||||
mov r12, ax2 ; fmt
|
||||
mov r14, ax3 ; va_list
|
||||
mov r15, ax1 ; n
|
||||
mov r17, ax0 ; putc
|
||||
nul r16 ; return value
|
||||
mov nx0, ax2 ; fmt
|
||||
mov nx2, ax3 ; va_list
|
||||
mov nx3, ax1 ; n
|
||||
mov nx5, ax0 ; putc
|
||||
nul nx4 ; return value
|
||||
|
||||
.main_loop:
|
||||
; find '%' or null-terminator
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov r13, r12
|
||||
scasb r13, '%'
|
||||
mov ecx, 0x7AFFFFFF
|
||||
mov nx1, nx0
|
||||
scasb nx1, '%'
|
||||
|
||||
; everything below r13 is a regular character; print it
|
||||
; everything below nx1 is a regular character; print it
|
||||
.print_regular:
|
||||
beq r12, r13, .check_modf
|
||||
beq nx0, nx1, .check_modf
|
||||
|
||||
call .doput, b[r12]
|
||||
call .doput, b[nx0]
|
||||
|
||||
inc r12
|
||||
inc nx0
|
||||
jmp .print_regular
|
||||
|
||||
.check_modf:
|
||||
; did we find a '%' ?
|
||||
; if not, then we found fmt's null-terminator; we're done
|
||||
bne b[r12], '%', .epilogue
|
||||
bne b[nx0], '%', .epilogue
|
||||
|
||||
; we did find a modifier / '%'
|
||||
mov rax, b[r12+1]
|
||||
add r12, 2
|
||||
mov eax, b[nx0+1]
|
||||
add nx0, 2
|
||||
|
||||
beq rax, 's', .modf_s
|
||||
beq rax, 'c', .modf_c
|
||||
beq rax, 'p', .modf_p
|
||||
beq rax, 'x', .modf_x
|
||||
beq rax, 'd', .modf_d
|
||||
beq rax, 'o', .modf_o
|
||||
beq rax, 'b', .modf_b
|
||||
beq rax, '%', .modf_percent
|
||||
beq eax, 's', .modf_s
|
||||
beq eax, 'c', .modf_c
|
||||
beq eax, 'p', .modf_p
|
||||
beq eax, 'x', .modf_x
|
||||
beq eax, 'd', .modf_d
|
||||
beq eax, 'o', .modf_o
|
||||
beq eax, 'b', .modf_b
|
||||
beq eax, '%', .modf_percent
|
||||
|
||||
; unrecognized
|
||||
jmp .bad_modifier
|
||||
|
||||
.modf_s:
|
||||
; get string address
|
||||
mov r13, q[r14]
|
||||
add r14, 8
|
||||
mov nx1, q[nx2]
|
||||
add nx2, 8
|
||||
|
||||
bzr r13, .nullstring
|
||||
bzr nx1, .nullstring
|
||||
|
||||
.print_string:
|
||||
movzx ax0, b[r13]
|
||||
movzx ax0, b[nx1]
|
||||
bzr ax0, .main_loop
|
||||
|
||||
inc r13
|
||||
inc nx1
|
||||
call .doput
|
||||
|
||||
jmp .print_string
|
||||
|
||||
.modf_c:
|
||||
call .doput, q[r14]
|
||||
add r14, 8
|
||||
call .doput, q[nx2]
|
||||
add nx2, 8
|
||||
|
||||
jmp .main_loop
|
||||
|
||||
@ -836,24 +836,24 @@ doprnt:
|
||||
|
||||
.print_number:
|
||||
; allocate itoa conversion buffer
|
||||
sub rsp, 80
|
||||
mov r13, rsp
|
||||
sub esp, 80
|
||||
mov nx1, esp
|
||||
|
||||
; assume modifier already set up ax2
|
||||
call itoa, rsp, q[r14]
|
||||
add r14, 8
|
||||
call itoa, esp, q[nx2]
|
||||
add nx2, 8
|
||||
|
||||
.print_itoa_buf:
|
||||
movzx ax0, b[r13]
|
||||
movzx ax0, b[nx1]
|
||||
|
||||
bzr ax0, .pib_end_loop
|
||||
inc r13
|
||||
inc nx1
|
||||
|
||||
call .doput
|
||||
jmp .print_itoa_buf
|
||||
|
||||
.pib_end_loop:
|
||||
add rsp, 80
|
||||
add esp, 80
|
||||
jmp .main_loop
|
||||
|
||||
.modf_percent:
|
||||
@ -879,11 +879,11 @@ doprnt:
|
||||
jmp .main_loop
|
||||
|
||||
.epilogue:
|
||||
mov rax, r16
|
||||
mov eax, nx4
|
||||
|
||||
pop r17, r16
|
||||
pop r15, r14
|
||||
pop r13, r12
|
||||
pop nx5, nx4
|
||||
pop nx3, nx2
|
||||
pop nx1, nx0
|
||||
|
||||
leave
|
||||
ret
|
||||
@ -892,23 +892,23 @@ doprnt:
|
||||
;
|
||||
.doput:
|
||||
; update print count
|
||||
inc r16
|
||||
inc nx4
|
||||
|
||||
; if n==0, don't print
|
||||
; we follow the C convention that sprintf()-like functions
|
||||
; should return the number of characters that would have
|
||||
; been printed/written if 'n' were big enough
|
||||
bzr r15, .r
|
||||
bzr nx3, .r
|
||||
|
||||
; decrement n and print
|
||||
dec r15
|
||||
call r17
|
||||
dec nx3
|
||||
call nx5
|
||||
|
||||
; did putc fail?
|
||||
jraxz .r
|
||||
jeaxz .r
|
||||
|
||||
; yes, so artificially set n=0
|
||||
nul r15
|
||||
nul nx3
|
||||
|
||||
.r:
|
||||
ret
|
||||
@ -922,7 +922,7 @@ doprnt:
|
||||
;
|
||||
putc:
|
||||
prn ax0
|
||||
nul rax
|
||||
nul eax
|
||||
ret
|
||||
|
||||
;
|
||||
@ -932,7 +932,7 @@ printf:
|
||||
mov ax2, ax0
|
||||
mov ax0, putc
|
||||
mov ax1, 0x7AFFFFFF
|
||||
add ax3, rsp, 8
|
||||
add ax3, esp, 8
|
||||
jmp doprnt
|
||||
|
||||
;
|
||||
@ -941,19 +941,19 @@ printf:
|
||||
nprintf:
|
||||
mov ax2, ax0
|
||||
mov ax0, putc
|
||||
add ax3, rsp, 8
|
||||
add ax3, esp, 8
|
||||
jmp doprnt
|
||||
|
||||
;
|
||||
; Print a string
|
||||
; Guaranteed to only affect rcx and ax0
|
||||
; Guaranteed to only affect ecx and ax0
|
||||
;
|
||||
print:
|
||||
.l:
|
||||
movzx rax, b[ax0]
|
||||
jraxz .r
|
||||
movzx eax, b[ax0]
|
||||
jeaxz .r
|
||||
|
||||
prn rax
|
||||
prn eax
|
||||
inc ax0
|
||||
|
||||
jmp .l
|
||||
@ -965,8 +965,8 @@ print:
|
||||
; Print exactly ax1 characters
|
||||
;
|
||||
nprint:
|
||||
mov rcx, ax1
|
||||
jrcxz .r
|
||||
mov ecx, ax1
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
prn b[ax0]
|
||||
@ -978,7 +978,7 @@ nprint:
|
||||
# 51 "crt/crt.k" 2
|
||||
|
||||
exit:
|
||||
mov rax, Sys.Exit
|
||||
mov eax, Sys.Exit
|
||||
trap 0
|
||||
|
||||
abort:
|
||||
@ -1044,7 +1044,7 @@ main:
|
||||
|
||||
; Fill .buf with user input
|
||||
scan eax
|
||||
jraxz .input_loop
|
||||
jeaxz .input_loop
|
||||
|
||||
; ESC key pressed?
|
||||
beq eax, 0x1B, .handle_EXIT
|
||||
@ -1053,7 +1053,7 @@ main:
|
||||
bne eax, 8, .handle_input
|
||||
|
||||
; anything to delete?
|
||||
jrcxz .input_loop ; no
|
||||
jecxz .input_loop ; no
|
||||
|
||||
; yes, delete it
|
||||
dec ecx
|
||||
@ -1088,7 +1088,7 @@ main:
|
||||
.extract_argv0:
|
||||
; did we read anything at all?
|
||||
; if not, just go back to waiting input
|
||||
jrcxz .print_prompt
|
||||
jecxz .print_prompt
|
||||
|
||||
; find first whitespace or null-terminator
|
||||
mov ecx, argbuf.size
|
||||
@ -1100,7 +1100,7 @@ main:
|
||||
|
||||
.next_space:
|
||||
mov ecx, b[esi]
|
||||
jrcxz .do_extract
|
||||
jecxz .do_extract
|
||||
|
||||
; skip spaces
|
||||
bne ecx, ' ', .not_a_space
|
||||
@ -1117,7 +1117,7 @@ main:
|
||||
.do_extract:
|
||||
; how much do we copy?
|
||||
sub ecx, edx, argbuf
|
||||
jrcxz .detect_builtin
|
||||
jecxz .detect_builtin
|
||||
dec ecx
|
||||
|
||||
mov edi, argbuf
|
||||
@ -1135,67 +1135,67 @@ main:
|
||||
|
||||
.builtin_cls = "cls"
|
||||
call strcmp, argv0, .builtin_cls
|
||||
jraxz .handle_CLS
|
||||
jeaxz .handle_CLS
|
||||
|
||||
.builtin_crash = "crash"
|
||||
call strcmp, argv0, .builtin_crash
|
||||
jraxz .handle_CRASH
|
||||
jeaxz .handle_CRASH
|
||||
|
||||
.builtin_date = "date"
|
||||
call strcmp, argv0, .builtin_date
|
||||
jraxz .handle_DATE
|
||||
jeaxz .handle_DATE
|
||||
|
||||
.builtin_dir = "dir"
|
||||
call strcmp, argv0, .builtin_dir
|
||||
jraxz .handle_DIR
|
||||
jeaxz .handle_DIR
|
||||
|
||||
.builtin_dump = "dump"
|
||||
call strcmp, argv0, .builtin_dump
|
||||
jraxz .handle_DUMP
|
||||
jeaxz .handle_DUMP
|
||||
|
||||
.builtin_echo = "echo"
|
||||
call strcmp, argv0, .builtin_echo
|
||||
jraxz .handle_ECHO
|
||||
jeaxz .handle_ECHO
|
||||
|
||||
.builtin_erase = "erase"
|
||||
call strcmp, argv0, .builtin_erase
|
||||
jraxz .handle_ERASE
|
||||
jeaxz .handle_ERASE
|
||||
|
||||
.builtin_exit = "exit"
|
||||
call strcmp, argv0, .builtin_exit
|
||||
jraxz .handle_EXIT
|
||||
jeaxz .handle_EXIT
|
||||
|
||||
.builtin_help = "help"
|
||||
call strcmp, argv0, .builtin_help
|
||||
jraxz .handle_HELP
|
||||
jeaxz .handle_HELP
|
||||
|
||||
.builtin_halt = "halt"
|
||||
call strcmp, argv0, .builtin_halt
|
||||
jraxz .handle_HALT
|
||||
jeaxz .handle_HALT
|
||||
|
||||
.builtin_make = "make"
|
||||
call strcmp, argv0, .builtin_make
|
||||
jraxz .handle_MAKE
|
||||
jeaxz .handle_MAKE
|
||||
|
||||
.builtin_print = "print"
|
||||
call strcmp, argv0, .builtin_print
|
||||
jraxz .handle_PRINT
|
||||
jeaxz .handle_PRINT
|
||||
|
||||
.builtin_prompt = "prompt"
|
||||
call strcmp, argv0, .builtin_prompt
|
||||
jraxz .handle_PROMPT
|
||||
jeaxz .handle_PROMPT
|
||||
|
||||
.builtin_remove = "remove"
|
||||
call strcmp, argv0, .builtin_remove
|
||||
jraxz .handle_REMOVE
|
||||
jeaxz .handle_REMOVE
|
||||
|
||||
.builtin_time = "time"
|
||||
call strcmp, argv0, .builtin_time
|
||||
jraxz .handle_TIME
|
||||
jeaxz .handle_TIME
|
||||
|
||||
.builtin_vers = "vers"
|
||||
call strcmp, argv0, .builtin_vers
|
||||
jraxz .handle_VERS
|
||||
jeaxz .handle_VERS
|
||||
|
||||
jmp .try_exec
|
||||
|
||||
@ -1237,7 +1237,7 @@ main:
|
||||
trap 0
|
||||
|
||||
.dir_list:
|
||||
jraxz .dir_end
|
||||
jeaxz .dir_end
|
||||
|
||||
mov nx3, ecx ; file size
|
||||
add nx2, ecx
|
||||
@ -1284,14 +1284,14 @@ main:
|
||||
; print and decrease ecx, unless it's already 0
|
||||
prn b[esi]
|
||||
inc esi
|
||||
jrcxz .dir_print_ext.1
|
||||
jecxz .dir_print_ext.1
|
||||
|
||||
dec ecx
|
||||
jmp .dir_print_ext.1
|
||||
|
||||
.dir_print_ext.2:
|
||||
; did we print at least 4 bytes?
|
||||
jrcxz .dir_print_bytes ; yes, carry on
|
||||
jecxz .dir_print_bytes ; yes, carry on
|
||||
|
||||
.dir_pe2.l:
|
||||
prn ' '
|
||||
@ -1413,7 +1413,7 @@ main:
|
||||
|
||||
; read anything?
|
||||
bltz ecx, .couldnt_read
|
||||
jrcxz .empty_file
|
||||
jecxz .empty_file
|
||||
|
||||
; all good, let's go
|
||||
mov eax, Sys.ExecuteInFrame
|
||||
@ -1469,7 +1469,7 @@ main:
|
||||
trap 0
|
||||
|
||||
bltz ecx, .couldnt_read
|
||||
jrcxz .empty_file
|
||||
jecxz .empty_file
|
||||
|
||||
call nprint, 0x108000, ecx
|
||||
|
||||
@ -1513,7 +1513,7 @@ main:
|
||||
|
||||
.handle_ECHO:
|
||||
mov eax, q[argv1pos]
|
||||
jraxz .echo.end
|
||||
jeaxz .echo.end
|
||||
|
||||
call print, eax
|
||||
|
||||
|
516
vm/ob/doskrnl.k
516
vm/ob/doskrnl.k
File diff suppressed because it is too large
Load Diff
368
vm/ob/hello.k
368
vm/ob/hello.k
@ -143,21 +143,21 @@ Sys.EnterHaltMode := 0x999
|
||||
; int strnlen(char *, int)
|
||||
;
|
||||
strnlen:
|
||||
mov rcx, ax1
|
||||
mov ecx, ax1
|
||||
scasb ax0, zero
|
||||
|
||||
sub rax, ax1, rcx
|
||||
sub eax, ax1, ecx
|
||||
ret
|
||||
|
||||
;
|
||||
; int strlen(char *)
|
||||
;
|
||||
strlen:
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov rdx, rcx
|
||||
mov ecx, 0x7AFFFFFF
|
||||
mov edx, ecx
|
||||
scasb ax0, zero
|
||||
|
||||
sub rax, rdx, rcx
|
||||
sub eax, edx, ecx
|
||||
ret
|
||||
|
||||
;
|
||||
@ -165,10 +165,10 @@ strlen:
|
||||
;
|
||||
strcpy:
|
||||
.l:
|
||||
mov rcx, b[ax1]
|
||||
mov b[ax0], rcx
|
||||
mov ecx, b[ax1]
|
||||
mov b[ax0], ecx
|
||||
|
||||
jrcxz .r
|
||||
jecxz .r
|
||||
|
||||
inc ax0
|
||||
inc ax1
|
||||
@ -182,8 +182,8 @@ strcpy:
|
||||
; void strncpy(char *, const char *, int)
|
||||
;
|
||||
strncpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
mov ecx, ax2
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
mov b[ax0], b[ax1]
|
||||
@ -200,14 +200,14 @@ strncpy:
|
||||
; void strnzcpy(char *, const char *, int)
|
||||
;
|
||||
strnzcpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
mov ecx, ax2
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
mov rax, b[ax1]
|
||||
mov b[ax0], rax
|
||||
mov eax, b[ax1]
|
||||
mov b[ax0], eax
|
||||
|
||||
jraxz .r
|
||||
jeaxz .r
|
||||
|
||||
inc ax0
|
||||
inc ax1
|
||||
@ -229,68 +229,68 @@ strnzcpy:
|
||||
; <0 if the first character that does not match has a lower value in str1 than in str2
|
||||
;
|
||||
strcmp:
|
||||
nul rsi
|
||||
nul esi
|
||||
.l:
|
||||
movzx rax, b[ax0+rsi]
|
||||
movzx rdx, b[ax1+rsi]
|
||||
movzx eax, b[ax0+esi]
|
||||
movzx edx, b[ax1+esi]
|
||||
|
||||
bne rax, rdx, .r
|
||||
bne eax, edx, .r
|
||||
|
||||
; both zero?
|
||||
add rcx, rax, rdx
|
||||
jrcxz .r
|
||||
add ecx, eax, edx
|
||||
jecxz .r
|
||||
|
||||
inc rsi
|
||||
inc esi
|
||||
jmp .l
|
||||
|
||||
.r:
|
||||
sub rax, rdx
|
||||
sub eax, edx
|
||||
ret
|
||||
|
||||
;
|
||||
; int strncmp(const char *str1, const char *str2, int maxn)
|
||||
;
|
||||
strncmp:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
mov ecx, ax2
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
movzx rax, b[ax0]
|
||||
movzx rdx, b[ax1]
|
||||
movzx eax, b[ax0]
|
||||
movzx edx, b[ax1]
|
||||
|
||||
bne rax, rdx, .r
|
||||
bne eax, edx, .r
|
||||
|
||||
inc ax0
|
||||
inc ax1
|
||||
loop .l
|
||||
|
||||
.r:
|
||||
sub rax, rdx
|
||||
sub eax, edx
|
||||
ret
|
||||
|
||||
;
|
||||
; char *strchrnul(const char *str, int ch)
|
||||
;
|
||||
strchrnul:
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov ecx, 0x7AFFFFFF
|
||||
scasb ax0, ax1
|
||||
|
||||
mov rax, ax0
|
||||
mov eax, ax0
|
||||
ret
|
||||
|
||||
;
|
||||
; char *strchr(const char *str, int ch)
|
||||
;
|
||||
strchr:
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov ecx, 0x7AFFFFFF
|
||||
scasb ax0, ax1
|
||||
|
||||
bnz b[ax0], .r
|
||||
nul rax
|
||||
nul eax
|
||||
ret
|
||||
|
||||
.r:
|
||||
mov rax, ax0
|
||||
mov eax, ax0
|
||||
ret
|
||||
|
||||
;
|
||||
@ -302,11 +302,11 @@ strrev:
|
||||
bzr b[ax1], .z
|
||||
|
||||
; save str's location
|
||||
mov rsi, ax1
|
||||
mov esi, ax1
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov ecx, 0x7AFFFFFF
|
||||
scasb ax1, zero
|
||||
dec ax1
|
||||
|
||||
@ -315,7 +315,7 @@ strrev:
|
||||
; and forward through buf
|
||||
mov b[ax0], b[ax1]
|
||||
|
||||
beq ax1, rsi, .r
|
||||
beq ax1, esi, .r
|
||||
|
||||
inc ax0
|
||||
dec ax1
|
||||
@ -341,7 +341,7 @@ strrev2:
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov ecx, 0x7AFFFFFF
|
||||
scasb ax1, zero
|
||||
dec ax1
|
||||
|
||||
@ -366,12 +366,12 @@ strrev2:
|
||||
; void memcpy(void *, const void *, int)
|
||||
;
|
||||
memcpy:
|
||||
mov rcx, ax2
|
||||
jrcxz .r
|
||||
mov ecx, ax2
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
sub rdx, ax2, rcx
|
||||
mov b[ax0+rdx], b[ax1+rdx]
|
||||
sub edx, ax2, ecx
|
||||
mov b[ax0+edx], b[ax1+edx]
|
||||
loop .l
|
||||
|
||||
.r:
|
||||
@ -381,8 +381,8 @@ memcpy:
|
||||
; void memzero(void *, int)
|
||||
;
|
||||
memzero:
|
||||
mov rcx, ax1
|
||||
jrcxz .r
|
||||
mov ecx, ax1
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
nul b[ax0]
|
||||
@ -416,22 +416,22 @@ memzero:
|
||||
; int DaysInYear(int year)
|
||||
;
|
||||
DaysInYear:
|
||||
mov rax, 365
|
||||
mov eax, 365
|
||||
|
||||
; divisible by 4?
|
||||
rem rcx, ax0, 4
|
||||
jrcxnz .end
|
||||
rem ecx, ax0, 4
|
||||
jecxnz .end
|
||||
|
||||
; divisible by 100?
|
||||
rem rcx, ax0, 100
|
||||
jrcxnz .leap
|
||||
rem ecx, ax0, 100
|
||||
jecxnz .leap
|
||||
|
||||
; divisible by 400?
|
||||
rem rcx, ax0, 400
|
||||
jrcxnz .end
|
||||
rem ecx, ax0, 400
|
||||
jecxnz .end
|
||||
|
||||
.leap:
|
||||
inc rax
|
||||
inc eax
|
||||
|
||||
.end:
|
||||
ret
|
||||
@ -442,37 +442,37 @@ DaysInYear:
|
||||
GetTimeUTC:
|
||||
ytime
|
||||
|
||||
mov rdi, .buf
|
||||
mov edi, .buf
|
||||
|
||||
; seconds
|
||||
rem rsi, rax, 60
|
||||
mov b[rdi], rsi
|
||||
rem esi, eax, 60
|
||||
mov b[edi], esi
|
||||
|
||||
; minutes
|
||||
div rsi, rax, 60
|
||||
rem rsi, 60
|
||||
mov b[rdi+1], rsi
|
||||
div esi, eax, 60
|
||||
rem esi, 60
|
||||
mov b[edi+1], esi
|
||||
|
||||
; hours
|
||||
div rsi, rax, 3600
|
||||
rem rsi, 24
|
||||
mov b[rdi+2], rsi
|
||||
div esi, eax, 3600
|
||||
rem esi, 24
|
||||
mov b[edi+2], esi
|
||||
|
||||
; month days
|
||||
div rsi, rax, 3600*24
|
||||
mov b[rdi+3], rsi
|
||||
div esi, eax, 3600*24
|
||||
mov b[edi+3], esi
|
||||
|
||||
; month
|
||||
mov b[rdi+4], rbx
|
||||
mov b[edi+4], rbx
|
||||
|
||||
; years
|
||||
mov w[rdi+6], rcx
|
||||
mov w[edi+6], ecx
|
||||
|
||||
;
|
||||
; ydays (TODO)
|
||||
;
|
||||
|
||||
mov rax, .buf
|
||||
mov eax, .buf
|
||||
ret
|
||||
|
||||
.buf = [24]
|
||||
@ -500,8 +500,8 @@ utoa:
|
||||
; void ltostr(char *buf, int num, int base, bool signed)
|
||||
;
|
||||
ltostr:
|
||||
mov rax, ax0
|
||||
nul rcx
|
||||
mov eax, ax0
|
||||
nul ecx
|
||||
|
||||
; make sure base is in [2, 32]
|
||||
bltu ax2, 2, .bad
|
||||
@ -515,8 +515,8 @@ ltostr:
|
||||
bzr ax3, .conv
|
||||
bne ax2, 10, .conv ; base 10
|
||||
|
||||
shr rcx, ax1, 63 ; extract ax1 sign
|
||||
jrcxz .conv
|
||||
shr ecx, ax1, 63 ; extract ax1 sign
|
||||
jecxz .conv
|
||||
|
||||
neg ax1 ; NEG if negative
|
||||
|
||||
@ -524,18 +524,18 @@ ltostr:
|
||||
.conv:
|
||||
bzr ax1, .fini
|
||||
|
||||
rem rdx, ax1, ax2 ; ax1 % base
|
||||
rem edx, ax1, ax2 ; ax1 % base
|
||||
|
||||
blt 9, rdx, .nondec ; rdx > 9 ?
|
||||
blt 9, edx, .nondec ; edx > 9 ?
|
||||
|
||||
add rdx, '0'
|
||||
add edx, '0'
|
||||
jmp .next
|
||||
|
||||
.nondec:
|
||||
add rdx, 55 ; 'A' - 10
|
||||
add edx, 55 ; 'A' - 10
|
||||
|
||||
.next:
|
||||
mov b[ax0], rdx
|
||||
mov b[ax0], edx
|
||||
|
||||
inc ax0
|
||||
|
||||
@ -544,14 +544,14 @@ ltostr:
|
||||
|
||||
; add minus flag, null-terminate and reverse
|
||||
.fini:
|
||||
jrcxz .cxz
|
||||
jecxz .cxz
|
||||
mov b[ax0], '-'
|
||||
inc ax0
|
||||
|
||||
.cxz:
|
||||
nul b[ax0]
|
||||
|
||||
call strrev2, rax
|
||||
call strrev2, eax
|
||||
ret
|
||||
|
||||
;
|
||||
@ -573,8 +573,8 @@ ltostr:
|
||||
;
|
||||
; int strtol(const char *str, int base)
|
||||
;
|
||||
; rax = integer extracted from str
|
||||
; rdx = pointer to first invalid byte
|
||||
; eax = integer extracted from str
|
||||
; edx = pointer to first invalid byte
|
||||
;
|
||||
strtol:
|
||||
mov ax2, 1
|
||||
@ -583,8 +583,8 @@ strtol:
|
||||
;
|
||||
; int strtoul(const char *str, int base)
|
||||
;
|
||||
; rax = integer extracted from str
|
||||
; rdx = pointer to first invalid byte
|
||||
; eax = integer extracted from str
|
||||
; edx = pointer to first invalid byte
|
||||
;
|
||||
strtoul:
|
||||
nul ax2
|
||||
@ -596,49 +596,49 @@ strtoul:
|
||||
; guesses base when 'base'=0
|
||||
;
|
||||
strtoq:
|
||||
nul rax, rsi
|
||||
mov rdx, ax0
|
||||
nul eax, esi
|
||||
mov edx, ax0
|
||||
|
||||
; make sure base is in [2, 32]
|
||||
beq ax1, 1, .bad
|
||||
bltu 36, ax1, .bad
|
||||
|
||||
; empty string?
|
||||
bzr b[rdx], .done
|
||||
bzr b[edx], .done
|
||||
|
||||
.skip_spc:
|
||||
bne b[rdx], ' ', .no_spc
|
||||
inc rdx
|
||||
bne b[edx], ' ', .no_spc
|
||||
inc edx
|
||||
jmp .skip_spc
|
||||
|
||||
.no_spc:
|
||||
; skip +
|
||||
bne b[rdx], '+', .no_plus
|
||||
inc rdx
|
||||
bne b[edx], '+', .no_plus
|
||||
inc edx
|
||||
|
||||
.no_plus:
|
||||
; unsigned?
|
||||
bzr ax2, .unsigned
|
||||
|
||||
; parse '-'
|
||||
bne b[rdx], '-', .unsigned
|
||||
inc rdx
|
||||
mov rsi, 1
|
||||
bne b[edx], '-', .unsigned
|
||||
inc edx
|
||||
mov esi, 1
|
||||
|
||||
.unsigned:
|
||||
; base 0
|
||||
bzr ax1, .base_0
|
||||
|
||||
; base prefix?
|
||||
bne b[rdx], '0', .main_loop
|
||||
bne b[edx], '0', .main_loop
|
||||
|
||||
inc rdx
|
||||
movzx rcx, b[rdx]
|
||||
inc edx
|
||||
movzx ecx, b[edx]
|
||||
|
||||
; "0x"/"0b" prefix
|
||||
jrcxz .done ; "0"
|
||||
beq rcx, 'x', .parsed_0x
|
||||
beq rcx, 'b', .parsed_0b
|
||||
jecxz .done ; "0"
|
||||
beq ecx, 'x', .parsed_0x
|
||||
beq ecx, 'b', .parsed_0b
|
||||
|
||||
; may be octal, but we don't care
|
||||
; we accept "0110101010" (despite base=2) for instance
|
||||
@ -646,40 +646,40 @@ strtoq:
|
||||
|
||||
.parsed_0x:
|
||||
; are we in base 16?
|
||||
; if not, leave rax = 0 and *rdx = 'x'
|
||||
; if not, leave eax = 0 and *edx = 'x'
|
||||
bne ax1, 16, .done
|
||||
; else
|
||||
inc rdx
|
||||
inc edx
|
||||
jmp .main_loop
|
||||
|
||||
.parsed_0b:
|
||||
; are we in base 2?
|
||||
; if not, leave rax = 0 and *rdx = 'b'
|
||||
; if not, leave eax = 0 and *edx = 'b'
|
||||
bne ax1, 2, .done
|
||||
; else
|
||||
inc rdx
|
||||
inc edx
|
||||
jmp .main_loop
|
||||
|
||||
.base_0:
|
||||
; guess base
|
||||
|
||||
beq b[rdx], '0', .b0_not10
|
||||
beq b[edx], '0', .b0_not10
|
||||
|
||||
; must be base 10
|
||||
mov ax1, 10
|
||||
jmp .main_loop
|
||||
|
||||
.b0_not10:
|
||||
inc rdx
|
||||
inc edx
|
||||
|
||||
bne b[rdx], 'x', .b0_not16
|
||||
inc rdx
|
||||
bne b[edx], 'x', .b0_not16
|
||||
inc edx
|
||||
mov ax1, 16
|
||||
jmp .main_loop
|
||||
|
||||
.b0_not16:
|
||||
bne b[rdx], 'b', .b0_not2
|
||||
inc rdx
|
||||
bne b[edx], 'b', .b0_not2
|
||||
inc edx
|
||||
mov ax1, 2
|
||||
jmp .main_loop
|
||||
|
||||
@ -688,45 +688,45 @@ strtoq:
|
||||
mov ax1, 8
|
||||
|
||||
.main_loop:
|
||||
movzx rcx, b[rdx]
|
||||
inc rdx
|
||||
movzx ecx, b[edx]
|
||||
inc edx
|
||||
|
||||
; between 0 and 9?
|
||||
bltu rcx, '0', .done
|
||||
bltu '9', rcx, .not_digit10
|
||||
bltu ecx, '0', .done
|
||||
bltu '9', ecx, .not_digit10
|
||||
|
||||
; yes
|
||||
sub rcx, '0'
|
||||
sub ecx, '0'
|
||||
jmp .next
|
||||
|
||||
.not_digit10:
|
||||
bltu rcx, 'A', .done
|
||||
bltu 'Z', rcx, .not_digitAZ
|
||||
bltu ecx, 'A', .done
|
||||
bltu 'Z', ecx, .not_digitAZ
|
||||
|
||||
sub rcx, 55 ; 'A' - 10
|
||||
sub ecx, 55 ; 'A' - 10
|
||||
jmp .next
|
||||
|
||||
.not_digitAZ:
|
||||
bltu rcx, 'a', .done
|
||||
bltu 'z', rcx, .done
|
||||
bltu ecx, 'a', .done
|
||||
bltu 'z', ecx, .done
|
||||
|
||||
sub rcx, 87 ; 'a' - 10
|
||||
sub ecx, 87 ; 'a' - 10
|
||||
jmp .next
|
||||
|
||||
.next:
|
||||
; too large for base?
|
||||
blteu ax1, rcx, .done
|
||||
blteu ax1, ecx, .done
|
||||
|
||||
mul rax, ax1
|
||||
add rax, rcx
|
||||
mul eax, ax1
|
||||
add eax, ecx
|
||||
jmp .main_loop
|
||||
|
||||
.done:
|
||||
; negative?
|
||||
bzr rsi, .r
|
||||
bzr esi, .r
|
||||
|
||||
; yes
|
||||
neg rax
|
||||
neg eax
|
||||
|
||||
.r:
|
||||
ret
|
||||
@ -743,73 +743,73 @@ strtoq:
|
||||
; int doprnt(PUTC putc, int n, const char *fmt, va_list ap)
|
||||
;
|
||||
doprnt:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
push r12, r13, r14
|
||||
push r15, r16, r17
|
||||
push nx0, nx1, nx2
|
||||
push nx3, nx4, nx5
|
||||
|
||||
mov r12, ax2 ; fmt
|
||||
mov r14, ax3 ; va_list
|
||||
mov r15, ax1 ; n
|
||||
mov r17, ax0 ; putc
|
||||
nul r16 ; return value
|
||||
mov nx0, ax2 ; fmt
|
||||
mov nx2, ax3 ; va_list
|
||||
mov nx3, ax1 ; n
|
||||
mov nx5, ax0 ; putc
|
||||
nul nx4 ; return value
|
||||
|
||||
.main_loop:
|
||||
; find '%' or null-terminator
|
||||
mov rcx, 0x7AFFFFFF
|
||||
mov r13, r12
|
||||
scasb r13, '%'
|
||||
mov ecx, 0x7AFFFFFF
|
||||
mov nx1, nx0
|
||||
scasb nx1, '%'
|
||||
|
||||
; everything below r13 is a regular character; print it
|
||||
; everything below nx1 is a regular character; print it
|
||||
.print_regular:
|
||||
beq r12, r13, .check_modf
|
||||
beq nx0, nx1, .check_modf
|
||||
|
||||
call .doput, b[r12]
|
||||
call .doput, b[nx0]
|
||||
|
||||
inc r12
|
||||
inc nx0
|
||||
jmp .print_regular
|
||||
|
||||
.check_modf:
|
||||
; did we find a '%' ?
|
||||
; if not, then we found fmt's null-terminator; we're done
|
||||
bne b[r12], '%', .epilogue
|
||||
bne b[nx0], '%', .epilogue
|
||||
|
||||
; we did find a modifier / '%'
|
||||
mov rax, b[r12+1]
|
||||
add r12, 2
|
||||
mov eax, b[nx0+1]
|
||||
add nx0, 2
|
||||
|
||||
beq rax, 's', .modf_s
|
||||
beq rax, 'c', .modf_c
|
||||
beq rax, 'p', .modf_p
|
||||
beq rax, 'x', .modf_x
|
||||
beq rax, 'd', .modf_d
|
||||
beq rax, 'o', .modf_o
|
||||
beq rax, 'b', .modf_b
|
||||
beq rax, '%', .modf_percent
|
||||
beq eax, 's', .modf_s
|
||||
beq eax, 'c', .modf_c
|
||||
beq eax, 'p', .modf_p
|
||||
beq eax, 'x', .modf_x
|
||||
beq eax, 'd', .modf_d
|
||||
beq eax, 'o', .modf_o
|
||||
beq eax, 'b', .modf_b
|
||||
beq eax, '%', .modf_percent
|
||||
|
||||
; unrecognized
|
||||
jmp .bad_modifier
|
||||
|
||||
.modf_s:
|
||||
; get string address
|
||||
mov r13, q[r14]
|
||||
add r14, 8
|
||||
mov nx1, q[nx2]
|
||||
add nx2, 8
|
||||
|
||||
bzr r13, .nullstring
|
||||
bzr nx1, .nullstring
|
||||
|
||||
.print_string:
|
||||
movzx ax0, b[r13]
|
||||
movzx ax0, b[nx1]
|
||||
bzr ax0, .main_loop
|
||||
|
||||
inc r13
|
||||
inc nx1
|
||||
call .doput
|
||||
|
||||
jmp .print_string
|
||||
|
||||
.modf_c:
|
||||
call .doput, q[r14]
|
||||
add r14, 8
|
||||
call .doput, q[nx2]
|
||||
add nx2, 8
|
||||
|
||||
jmp .main_loop
|
||||
|
||||
@ -836,24 +836,24 @@ doprnt:
|
||||
|
||||
.print_number:
|
||||
; allocate itoa conversion buffer
|
||||
sub rsp, 80
|
||||
mov r13, rsp
|
||||
sub esp, 80
|
||||
mov nx1, esp
|
||||
|
||||
; assume modifier already set up ax2
|
||||
call itoa, rsp, q[r14]
|
||||
add r14, 8
|
||||
call itoa, esp, q[nx2]
|
||||
add nx2, 8
|
||||
|
||||
.print_itoa_buf:
|
||||
movzx ax0, b[r13]
|
||||
movzx ax0, b[nx1]
|
||||
|
||||
bzr ax0, .pib_end_loop
|
||||
inc r13
|
||||
inc nx1
|
||||
|
||||
call .doput
|
||||
jmp .print_itoa_buf
|
||||
|
||||
.pib_end_loop:
|
||||
add rsp, 80
|
||||
add esp, 80
|
||||
jmp .main_loop
|
||||
|
||||
.modf_percent:
|
||||
@ -879,11 +879,11 @@ doprnt:
|
||||
jmp .main_loop
|
||||
|
||||
.epilogue:
|
||||
mov rax, r16
|
||||
mov eax, nx4
|
||||
|
||||
pop r17, r16
|
||||
pop r15, r14
|
||||
pop r13, r12
|
||||
pop nx5, nx4
|
||||
pop nx3, nx2
|
||||
pop nx1, nx0
|
||||
|
||||
leave
|
||||
ret
|
||||
@ -892,23 +892,23 @@ doprnt:
|
||||
;
|
||||
.doput:
|
||||
; update print count
|
||||
inc r16
|
||||
inc nx4
|
||||
|
||||
; if n==0, don't print
|
||||
; we follow the C convention that sprintf()-like functions
|
||||
; should return the number of characters that would have
|
||||
; been printed/written if 'n' were big enough
|
||||
bzr r15, .r
|
||||
bzr nx3, .r
|
||||
|
||||
; decrement n and print
|
||||
dec r15
|
||||
call r17
|
||||
dec nx3
|
||||
call nx5
|
||||
|
||||
; did putc fail?
|
||||
jraxz .r
|
||||
jeaxz .r
|
||||
|
||||
; yes, so artificially set n=0
|
||||
nul r15
|
||||
nul nx3
|
||||
|
||||
.r:
|
||||
ret
|
||||
@ -922,7 +922,7 @@ doprnt:
|
||||
;
|
||||
putc:
|
||||
prn ax0
|
||||
nul rax
|
||||
nul eax
|
||||
ret
|
||||
|
||||
;
|
||||
@ -932,7 +932,7 @@ printf:
|
||||
mov ax2, ax0
|
||||
mov ax0, putc
|
||||
mov ax1, 0x7AFFFFFF
|
||||
add ax3, rsp, 8
|
||||
add ax3, esp, 8
|
||||
jmp doprnt
|
||||
|
||||
;
|
||||
@ -941,19 +941,19 @@ printf:
|
||||
nprintf:
|
||||
mov ax2, ax0
|
||||
mov ax0, putc
|
||||
add ax3, rsp, 8
|
||||
add ax3, esp, 8
|
||||
jmp doprnt
|
||||
|
||||
;
|
||||
; Print a string
|
||||
; Guaranteed to only affect rcx and ax0
|
||||
; Guaranteed to only affect ecx and ax0
|
||||
;
|
||||
print:
|
||||
.l:
|
||||
movzx rax, b[ax0]
|
||||
jraxz .r
|
||||
movzx eax, b[ax0]
|
||||
jeaxz .r
|
||||
|
||||
prn rax
|
||||
prn eax
|
||||
inc ax0
|
||||
|
||||
jmp .l
|
||||
@ -965,8 +965,8 @@ print:
|
||||
; Print exactly ax1 characters
|
||||
;
|
||||
nprint:
|
||||
mov rcx, ax1
|
||||
jrcxz .r
|
||||
mov ecx, ax1
|
||||
jecxz .r
|
||||
|
||||
.l:
|
||||
prn b[ax0]
|
||||
@ -978,7 +978,7 @@ nprint:
|
||||
# 51 "crt/crt.k" 2
|
||||
|
||||
exit:
|
||||
mov rax, Sys.Exit
|
||||
mov eax, Sys.Exit
|
||||
trap 0
|
||||
|
||||
abort:
|
||||
|
@ -13,32 +13,32 @@
|
||||
|
||||
static uchar fetchb(void)
|
||||
{
|
||||
uchar v = *(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
|
||||
R(RIP) += 1;
|
||||
uchar v = *(ctx->mp + R(EIP) + R(CR1) - MEMOFF);
|
||||
R(EIP) += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static ushort fetchw(void)
|
||||
{
|
||||
ushort v = *(ushort *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
|
||||
R(RIP) += 2;
|
||||
ushort v = *(ushort *)(ctx->mp + R(EIP) + R(CR1) - MEMOFF);
|
||||
R(EIP) += 2;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static uint fetchd(void)
|
||||
{
|
||||
uint v = *(uint *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
|
||||
R(RIP) += 4;
|
||||
uint v = *(uint *)(ctx->mp + R(EIP) + R(CR1) - MEMOFF);
|
||||
R(EIP) += 4;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static ulong fetchq(void)
|
||||
{
|
||||
ulong v = *(ulong *)(ctx->mp + R(RIP) + R(CR1) - MEMOFF);
|
||||
R(RIP) += 8;
|
||||
ulong v = *(ulong *)(ctx->mp + R(EIP) + R(CR1) - MEMOFF);
|
||||
R(EIP) += 8;
|
||||
|
||||
return v;
|
||||
}
|
||||
@ -158,7 +158,7 @@ static void extract_param(instr_t *in, acc_t *p)
|
||||
p->type = AM_RRI;
|
||||
p->reg1 = fetchb();
|
||||
p->imm2 = (short)fetchw();
|
||||
p->reg2 = RZX;
|
||||
p->reg2 = EZX;
|
||||
p->imm1 = 1;
|
||||
break;
|
||||
|
||||
@ -182,7 +182,7 @@ static void extract_param(instr_t *in, acc_t *p)
|
||||
p->type = AM_RRI;
|
||||
p->reg1 = fetchb();
|
||||
p->imm2 = fetchq();
|
||||
p->reg2 = RZX;
|
||||
p->reg2 = EZX;
|
||||
p->imm1 = 1;
|
||||
break;
|
||||
}
|
||||
@ -201,11 +201,11 @@ void decode(void)
|
||||
|
||||
//logerr("decodin'\n");
|
||||
|
||||
ctx->cur_pc = R(RIP);
|
||||
ctx->cur_pc = R(EIP);
|
||||
|
||||
// Address range check
|
||||
// (assumes max. instruction length is 32 bytes)
|
||||
if (R(RIP) + R(CR1) - MEMOFF >= ctx->mz - 32)
|
||||
if (R(EIP) + R(CR1) - MEMOFF >= ctx->mz - 32)
|
||||
_except(E_ACC, "Executing out of memory");
|
||||
|
||||
// Instruction bytes
|
||||
|
@ -89,10 +89,10 @@ void _except(int _code, char *fmt, ...)
|
||||
ctx->rf = rfs[handler];
|
||||
rfs_current_idx = handler;
|
||||
|
||||
R(R12) = code;
|
||||
R(R13) = effcode;
|
||||
R(R14) = orig_frame;
|
||||
R(R15) = R(RIP);
|
||||
R(NX0) = code;
|
||||
R(NX1) = effcode;
|
||||
R(NX2) = orig_frame;
|
||||
R(NX3) = R(EIP);
|
||||
|
||||
idt_handling[effcode]++;
|
||||
|
||||
|
@ -36,7 +36,7 @@ void exec_instr(instr_t *in,
|
||||
if (__builtin_expect(out == 2, 0))
|
||||
OUTPUT(p2, r2);
|
||||
|
||||
R(RZX) = 0;
|
||||
R(EZX) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ int main(int argc, char **argv)
|
||||
main_ctx.mp = malloc(MEMSIZE + 16);
|
||||
main_ctx.mz = MEMSIZE;
|
||||
|
||||
main_ctx.rf[RIP] = MEMOFF;
|
||||
main_ctx.rf[EIP] = MEMOFF;
|
||||
|
||||
if (main_ctx.mp == 0) {
|
||||
logerr("Couldn't allocate RAM\n");
|
||||
@ -115,7 +115,7 @@ int main(int argc, char **argv)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memcpy(&main_ctx.mp[addr2real(main_ctx.rf[RIP])], fwprog, fwsize);
|
||||
memcpy(&main_ctx.mp[addr2real(main_ctx.rf[EIP])], fwprog, fwsize);
|
||||
|
||||
//
|
||||
// Devices initialization
|
||||
|
26
vm/pc/regs.c
26
vm/pc/regs.c
@ -5,13 +5,13 @@
|
||||
|
||||
reg_t arch_r[] =
|
||||
{
|
||||
{ "rax", GPR }, { "rbx", GPR }, { "rcx", GPR }, { "rdx", GPR },
|
||||
{ "rsi", GPR }, { "rdi", GPR }, { "ax0", GPR }, { "ax1", GPR },
|
||||
{ "eax", GPR }, { "ebx", GPR }, { "ecx", GPR }, { "edx", GPR },
|
||||
{ "esi", GPR }, { "edi", GPR }, { "ax0", GPR }, { "ax1", GPR },
|
||||
{ "ax2", GPR }, { "ax3", GPR }, { "ax4", GPR }, { "ax5", GPR },
|
||||
|
||||
{ "r12", GPR }, { "r13", GPR }, { "r14", GPR }, { "r15", GPR },
|
||||
{ "r16", GPR }, { "r17", GPR }, { "r18", GPR }, { "r19", GPR },
|
||||
{ "r20", GPR }, { "grp", GPR }, { "trp", GPR }, { "srp", SYS },
|
||||
{ "nx0", GPR }, { "nx1", GPR }, { "nx2", GPR }, { "nx3", GPR },
|
||||
{ "nx4", GPR }, { "nx5", GPR }, { "nx6", GPR }, { "nx7", GPR },
|
||||
{ "nx8", GPR }, { "grp", GPR }, { "trp", GPR }, { "srp", SYS },
|
||||
|
||||
{ "tmp", GPR }, { "rad", GPR }, { "cr0", SYS }, { "cr1", SYS },
|
||||
{ "rip", GPR }, { "rbp", GPR }, { "rsp", GPR }, { "zero", GPR },
|
||||
@ -26,11 +26,11 @@ void dumpregs()
|
||||
TRACE("Current RFRAME index: #%lu", rfs_current_idx);
|
||||
|
||||
TRACE("\n\nEnviron #1:");
|
||||
TRACE("\nrpc=0x%-16lX rip=0x%-16lX", ctx->cur_pc, R(RIP));
|
||||
TRACE("\nepc=0x%-16lX eip=0x%-16lX", ctx->cur_pc, R(EIP));
|
||||
TRACE("\ncr0=0x%-16lX cr1=0x%-16lX", R(CR0), R(CR1));
|
||||
|
||||
TRACE("\n\nEnviron #2:");
|
||||
TRACE("\nrsp=0x%-16lX rbp=0x%-16lX ins=0d%-16lu", R(RSP), R(RBP), ctx->ninstrs);
|
||||
TRACE("\nesp=0x%-16lX ebp=0x%-16lX ins=0d%-16lu", R(ESP), R(EBP), ctx->ninstrs);
|
||||
TRACE("\ngrp=0x%-16lX trp=0x%-16lX srp=0x%-16lX", R(GRP), R(TRP), R(SRP));
|
||||
|
||||
TRACE("\n\nArgument:");
|
||||
@ -38,16 +38,16 @@ void dumpregs()
|
||||
TRACE("\nax3=0x%-16lX ax4=0x%-16lX ax5=0x%-16lX", R(AX3), R(AX4), R(AX5));
|
||||
|
||||
TRACE("\n\nVolatile:");
|
||||
TRACE("\nrax=0x%-16lX rbx=0x%-16lX rcx=0x%-16lX", R(RAX), R(RBX), R(RCX));
|
||||
TRACE("\nrdx=0x%-16lX rsi=0x%-16lX rdi=0x%-16lX", R(RDX), R(RSI), R(RDI));
|
||||
TRACE("\neax=0x%-16lX ebx=0x%-16lX ecx=0x%-16lX", R(EAX), R(EBX), R(ECX));
|
||||
TRACE("\nedx=0x%-16lX esi=0x%-16lX edi=0x%-16lX", R(EDX), R(ESI), R(EDI));
|
||||
|
||||
TRACE("\n\nPersistent:");
|
||||
TRACE("\nr12=0x%-16lX r13=0x%-16lX r14=0x%-16lX", R(R12), R(R13), R(R14));
|
||||
TRACE("\nr15=0x%-16lX r16=0x%-16lX r17=0x%-16lX", R(R15), R(R16), R(R17));
|
||||
TRACE("\nr18=0x%-16lX r19=0x%-16lX r20=0x%-16lX", R(R18), R(R19), R(R20));
|
||||
TRACE("\nnx0=0x%-16lX nx1=0x%-16lX nx2=0x%-16lX", R(NX0), R(NX1), R(NX2));
|
||||
TRACE("\nnx3=0x%-16lX nx4=0x%-16lX nx5=0x%-16lX", R(NX3), R(NX4), R(NX5));
|
||||
TRACE("\nnx6=0x%-16lX nx7=0x%-16lX nx8=0x%-16lX", R(NX6), R(NX7), R(NX8));
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
assert(R(RZX) == 0);
|
||||
assert(R(EZX) == 0);
|
||||
}
|
||||
|
||||
|
21
vm/pc/regs.h
21
vm/pc/regs.h
@ -9,19 +9,6 @@ enum
|
||||
SYS = 1 << 1, // Reserved for supervisor mode
|
||||
};
|
||||
|
||||
// FLG register
|
||||
enum
|
||||
{
|
||||
ZF = 1 << 0, // Zero flag
|
||||
SF = 1 << 1, // Sign flag
|
||||
|
||||
CF = 1 << 4, // Carry flag
|
||||
OF = 1 << 5, // Overflow flag
|
||||
|
||||
PF = 1 << 8, // Parity flag
|
||||
DF = 1 << 9, // Direction flag
|
||||
};
|
||||
|
||||
// CR0 register
|
||||
enum
|
||||
{
|
||||
@ -37,10 +24,10 @@ struct reg_t
|
||||
|
||||
enum
|
||||
{
|
||||
RAX, RBX, RCX, RDX, RSI, RDI, AX0, AX1,
|
||||
AX2, AX3, AX4, AX5, R12, R13, R14, R15,
|
||||
R16, R17, R18, R19, R20, GRP, TRP, SRP,
|
||||
TMP, RAD, CR0, CR1, RIP, RBP, RSP, RZX,
|
||||
EAX, EBX, ECX, EDX, ESI, EDI, AX0, AX1,
|
||||
AX2, AX3, AX4, AX5, NX0, NX1, NX2, NX3,
|
||||
NX4, NX5, NX6, NX7, NX8, GRP, TRP, SRP,
|
||||
TMP, RAD, CR0, CR1, EIP, EBP, ESP, EZX,
|
||||
|
||||
NREGS
|
||||
};
|
||||
|
@ -18,7 +18,7 @@ int create_symtab(const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fscanf(tab, "%45s%*s %lu\n", buf, &addr) > 0 && it < SYMTAB_LEN)
|
||||
while (fscanf(tab, "%45s %lu\n", buf, &addr) > 0 && it < SYMTAB_LEN)
|
||||
{
|
||||
//trace("SYM: '%.*s' '%lu'\n", SYMLEN_MAX, buf, addr);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user