wip, the urge to finish the lookup table is real...

This commit is contained in:
Edward R. Gonzalez 2023-03-06 07:33:25 -05:00
parent 356d8076a5
commit 3c712f8be6
15 changed files with 851 additions and 192 deletions

View File

@ -3,6 +3,7 @@
"*.rmd": "markdown",
"zpl.h": "c",
"cstddef": "cpp",
"xtr1common": "cpp"
"xtr1common": "cpp",
"*.inline": "cpp"
}
}

51
8086/Op.hpp Normal file
View File

@ -0,0 +1,51 @@
#include "bloat.hpp"
namespace Op
{
enum Code : u8
{
#define D_Entry( Entry_ ) Entry,
#include "opcodes.inline"
Num,
#undef D_Entry
};
char const* str( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.inline"
#undef D_Entry
};
return code_to_str[ code ];
}
char const* meumonic( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.meumonics.inline"
#undef D_Entry
};
return code_to_str[ code ];
}
char const* intuitive( Code code )
{
static
char const* code_to_str[ Num] =
{
#define D_Entry( Entry_ ) ZPL_STRINGIFY( Entry_ ),
#include "opcodes.intuitive.inline"
#undef D_Entry
};
return code_to_str[ Num];
}
}

146
8086/opcodes.inline Normal file
View File

@ -0,0 +1,146 @@
D_Entry( add_00 )
D_Entry( add_01 )
D_Entry( add_02 )
D_Entry( add_04 )
D_Entry( add_05 )
D_Entry( push_06 )
D_Entry( pop_07 )
D_Entry( or_10 )
D_Entry( or_11 )
D_Entry( or_12 )
D_Entry( or_13 )
D_Entry( or_14 )
D_Entry( or_15 )
D_Entry( push_16 )
D_Entry( _17 )
D_Entry( adc_20 )
D_Entry( adc_21 )
D_Entry( adc_22 )
D_Entry( adc_23 )
D_Entry( adc_24 )
D_Entry( adc_25 )
D_Entry( push_26 )
D_Entry( pop_27 )
D_Entry( sbb_30 )
D_Entry( sbb_31 )
D_Entry( sbb_32 )
D_Entry( sbb_33 )
D_Entry( sbb_34 )
D_Entry( sbb_35 )
D_Entry( push_36 )
D_Entry( pop_37 )
D_Entry( and_40 )
D_Entry( and_41 )
D_Entry( and_42 )
D_Entry( and_43 )
D_Entry( and_44 )
D_Entry( and_45 )
D_Entry( es_46 )
D_Entry( daa_47 )
D_Entry( sub_50 )
D_Entry( sub_51 )
D_Entry( sub_52 )
D_Entry( sub_53 )
D_Entry( sub_54 )
D_Entry( sub_55 )
D_Entry( cs_56 )
D_Entry( das_57 )
D_Entry( xor_60 )
D_Entry( xor_61 )
D_Entry( xor_62 )
D_Entry( xor_63 )
D_Entry( xor_64 )
D_Entry( xor_65 )
D_Entry( ss_66 )
D_Entry( aaa_67 )
D_Entry( cmp_70 )
D_Entry( cmp_71 )
D_Entry( cmp_72 )
D_Entry( cmp_73 )
D_Entry( cmp_74 )
D_Entry( cmp_75 )
D_Entry( ds_75 )
D_Entry( ds_76 )
D_Entry( aas_107 )
D_Entry( inc_100 )
D_Entry( inc_101 )
D_Entry( inc_102 )
D_Entry( inc_103 )
D_Entry( inc_104 )
D_Entry( inc_105 )
D_Entry( inc_106 )
D_Entry( inc_107 )
D_Entry( dec_100 )
D_Entry( dec_101 )
D_Entry( dec_102 )
D_Entry( dec_103 )
D_Entry( dec_104 )
D_Entry( dec_105 )
D_Entry( dec_106 )
D_Entry( dec_107 )
D_Entry( push_110 )
D_Entry( push_111 )
D_Entry( push_112 )
D_Entry( push_113 )
D_Entry( push_114 )
D_Entry( push_115 )
D_Entry( push_116 )
D_Entry( push_117 )
D_Entry( pop_120 )
D_Entry( pop_121 )
D_Entry( pop_122 )
D_Entry( pop_123 )
D_Entry( pop_124 )
D_Entry( pop_125 )
D_Entry( pop_126 )
D_Entry( pop_127 )
D_Entry( pop_130 )
D_Entry( pop_131 )
D_Entry( pop_132 )
D_Entry( pop_133 )
D_Entry( pop_134 )
D_Entry( pop_135 )
D_Entry( pop_136 )
D_Entry( pop_137 )
D_Entry( _140 )
D_Entry( _141 )
D_Entry( _142 )
D_Entry( _143 )
D_Entry( _144 )
D_Entry( _145 )
D_Entry( _146 )
D_Entry( _147 )
D_Entry( _150 )
D_Entry( _151 )
D_Entry( _152 )
D_Entry( _153 )
D_Entry( _154 )
D_Entry( _155 )
D_Entry( _156 )
D_Entry( _157 )
D_Entry( jo_160 )
D_Entry( jno_161 )
D_Entry( jb_jnae_jc_162 )
D_Entry( jnb_jae_jnc_163 )
D_Entry( je_jz_164 )
D_Entry( jne_jnz_165 )
D_Entry( jbe_jna_166 )
D_Entry( jnbe_ja_167 )
D_Entry( js_170 )
D_Entry( jns_171 )
D_Entry( jp_jpe_172 )
D_Entry( jnp_jpo_173 )
D_Entry( jl_jnge_174 )
D_Entry( jnl_jge_175 )
D_Entry( jle_jng_176 )
D_Entry( jnle_jg_177 )
D_Entry( add_200 )
D_Entry( or_201 )
D_Entry( adc_201 )
D_Entry( sbb_202 )
D_Entry( sub_203 )
D_Entry( cmp_204 )
D_Entry( add_205 )
D_Entry( adc_206 )
D_Entry( sbb_207 )
D_Entry( sub_210 )

View File

View File

View File

@ -30,22 +30,101 @@
// # define ZPL_MODULE_THREADING
// # define ZPL_MODULE_JOBS
// # define ZPL_MODULE_PARSER
extern "C" {
// extern "C" {
#include "zpl.h"
}
// }
#if __clang__
# pragma clang diagnostic pop
#endif
#undef cast
#pragma endregion ZPL INCLUDE
zpl_arena Global_Arena {};
#define g_allocator zpl_arena_allocator( & Global_Arena)
void setup()
{
zpl_arena_init_from_allocator( & Global_Arena, zpl_heap(), zpl_megabytes(10) );
if ( Global_Arena.total_size == 0 )
{
zpl_assert_crash( "Failed to reserve memory for Tests:: Global_Arena" );
}
}
void cleanup()
{
zpl_arena_free( & Global_Arena);
}
#pragma region ZPL Expose
zpl_string string_make(zpl_isize capacity)
{
zpl_isize header_size = zpl_size_of(zpl_string_header);
void *ptr = zpl_alloc(g_allocator, header_size + capacity + 1);
zpl_string str;
zpl_string_header *header;
if (ptr == NULL) return NULL;
zpl_zero_size(ptr, header_size + capacity + 1);
str = cast(char *) ptr + header_size;
header = ZPL_STRING_HEADER(str);
header->allocator = g_allocator;
header->length = 0;
header->capacity = capacity;
str[capacity] = '\0';
return str;
}
inline
zpl_string string_make(const char *str)
{
zpl_isize len = str ? zpl_strlen(str) : 0;
return zpl_string_make_length(g_allocator, str, len);
}
inline
zpl_string string_append(zpl_string str, zpl_string const other)
{
return zpl_string_append_length(str, other, zpl_string_length(other));
}
zpl_string string_format( char const* fmt, ... )
{
zpl_local_persist zpl_thread_local char buf[ZPL_PRINTF_MAXLEN] = { 0 };
va_list va;
va_start(va, fmt);
zpl_snprintf_va(buf, ZPL_PRINTF_MAXLEN, fmt, va);
va_end(va);
return zpl_string_make(g_allocator, buf);
}
zpl_string string_format( char* buffer, zpl_isize size, char const* fmt, ... )
{
va_list va;
va_start(va, fmt);
zpl_snprintf_va(buffer, size, fmt, va);
va_end(va);
return zpl_string_make(g_allocator, buffer);
}
#pragma endregion ZPL Expose
#define bit( Value_ ) ( 1 << Value_ )
#define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ )
#undef cast
#define cast( Type_ , Value_ ) ( ( Type_ )( Value_ ) )
#define ct constexpr
#define gen( ... ) template< __VA_ARGS__ >
@ -54,13 +133,31 @@ extern "C" {
#define Msg_Invalid_Value "INVALID VALUE PROVIDED"
#define scast static_cast
#define rcast reinterpret_cast
#define pcast( Type_, Value_ ) ( * (Type_*)( & Value_ ) )
using s8 = zpl_i8;
using u8 = zpl_u8;
using u16 = zpl_u16;
using u32 = zpl_u32;
using f64 = zpl_f64;
using uw = zpl_usize;
using sw = zpl_isize;
struct u16_Split
{
u8 Low;
u8 High;
operator u16()
{
return * cast( u16*, this );
}
};
ct inline
char char_binary( u8 value, u8 pos )
{

View File

@ -15,5 +15,15 @@ if not exist tests\listing_0038_many_register_mov (
call nasm ".\tests\listing_0038_many_register_mov.asm"
)
if not exist tests\listing_0039_more_movs (
echo Assembling: listing_0039_more_movs.asm
call nasm ".\tests\listing_0039_more_movs.asm"
)
if not exist tests\listing_0040_challenge_movs (
echo Assembling: listing_0040_challenge_movs.asm
call nasm ".\tests\listing_0040_challenge_movs.asm"
)
echo:
ninja -C build

View File

@ -11,3 +11,12 @@ if exist tests\listing_0037_single_register_mov (
if exist tests\listing_0038_many_register_mov (
DEL /Q tests\listing_0038_many_register_mov
)
if exist tests\listing_0039_more_movs (
DEL /Q tests\listing_0039_more_movs
)
if exist tests\listing_0040_challenge_movs (
DEL /Q tests\listing_0040_challenge_movs
)

View File

@ -1,60 +1,46 @@
#include "bloat.hpp"
zpl_arena BlobArena {};
#define allocator zpl_arena_allocator( & BlobArena)
void setup()
{
zpl_arena_init_from_allocator( & BlobArena, zpl_heap(), zpl_megabytes(10) );
if ( BlobArena.total_size == 0 )
{
zpl_assert_crash( "Failed to reserve memory for Tests:: BLobArena" );
}
}
void cleanup()
{
zpl_arena_free( & BlobArena);
}
// Binary formatting for literals is used heavily as that its
// how the encoding is conveyed in the hardware reference from intel.
// Octal formatting is used heavily throughout
// See: https://gist.github.com/seanjensengrey/f971c20d05d4d0efc0781f2f3c0353da
// (x86 is an octal machine)
namespace Op
{
ct u8 Mask = 00210;
ct u8 Mask_Low = 0b11110000;
ct u8 Mask_High = 0b00001111;
ct u8 Mask_Imme = 0b00111000;
#define D_Opcodes \
D_Entry( mov_88 ) \
D_Entry( mov_89 ) \
D_Entry( mov_RM_R ) \
D_Entry( mov_Im_RM ) \
D_Entry( mov_Im_R ) \
D_Entry( mov_M_Acc ) \
D_Entry( mov_Acc_M ) \
D_Entry( mov_RM_SR ) \
D_Entry( mov_SR_RM ) \
enum Code : u8
{
Mask = 0b11111100,
mov_88 = 0b10001000,
mov_89 = 0b11000100,
mov_RM_R = 0b10001000,
mov_Im_RM = 0b11001100,
mov_Im_R = 0b10110000,
mov_M_Acc = 0b10100000,
mov_Acc_M = 0b10100010,
mov_RM_SR = 0b10001110,
mov_SR_RM = 0b10001100
};
char const* str( Code type )
{
switch ( type )
{
case mov_88:
return "mov_88";
case mov_89:
return "mov_89";
}
#define D_Entry( Entry_ ) \
case Entry_: \
return ZPL_STRINGIFY(Entry_); \
return Msg_Invalid_Value;
}
ct char const* helper_meumonic( Code type )
{
switch ( type )
{
case mov_88:
case mov_89:
return "mov";
D_Opcodes
#undef D_Entry
}
return Msg_Invalid_Value;
@ -64,32 +50,30 @@ namespace Op
{
switch ( type )
{
case mov_88:
case mov_89:
case mov_RM_R :
case mov_Im_RM :
case mov_Im_R :
case mov_M_Acc :
case mov_Acc_M :
case mov_RM_SR :
case mov_SR_RM :
return "mov";
}
return Msg_Invalid_Value;
}
ct char const* helper_intuitive( Code type )
{
switch ( type )
{
case mov_88:
case mov_89:
return "move";
}
return Msg_Invalid_Value;
}
char const* intuitive( Code type )
{
switch ( type )
{
case mov_88:
case mov_89:
case mov_RM_R :
case mov_Im_RM :
case mov_Im_R :
case mov_M_Acc :
case mov_Acc_M :
case mov_RM_SR :
case mov_SR_RM :
return "move";
}
@ -101,9 +85,8 @@ namespace Op
namespace Field
{
// Effective Address offset
inline
u8 effective_address( u8 reg )
u8 offset_left_reg( u8 reg )
{
return reg << 3;
}
@ -134,9 +117,10 @@ namespace Field
// https://i.imgur.com/9Op8Lnd.png
enum Width : u8
{
Mask_Width = 0b00000001,
Width_Byte = 0b00,
Width_Word = 0b01,
Mask_Width = 0b00000001,
Mask_Width_Imme = 0b00001000,
Width_Byte = 0b00,
Width_Word = 0b01,
};
inline
@ -184,37 +168,81 @@ namespace Field
return Msg_Invalid_Value;
}
#if 0
ct u8 RegMem_AL = 0b00000000;
ct u8 RegMem_AX = 0b00000000;
ct u8 RegMem_BX_SI = 0b00000000;
ct u8 RegMem_BX_SI_D8 = 0b00000000;
ct u8 RegMem_BX_SI_D16 = 0b00000000;
#endif
ct u8 Mask_Memory = 0b00000111;
// https://i.imgur.com/Tm5roJu.png
enum Memory : u8
{
Add_BX_SI = 0b000,
Add_BX_DI = 0b001,
Add_BP_SI = 0b010,
Add_BP_DI = 0b011,
Add_SI = 0b100,
Add_DI = 0b101,
Add_Direct = 0b110,
Add_BX = 0b111,
Num_Memory
};
char const* str_memory( Memory mem )
{
char const* mem_to_str[Num_Memory] =
{
"BX + SI",
"BX + DI",
"BP + SI",
"BP + DI",
"SI",
"DI",
"BP",
"BX"
};
return mem_to_str[ mem ];
}
char const* str_memory_intuitive( Memory mem )
{
char const* mem_to_str[Num_Memory] =
{
"Base.16 + Stack.Index",
"Base.16 + Destination.Index",
"Stack.Base + Stack.Index",
"Stack.Base + Destination.Index",
"Stack.Index",
"Destination.Index",
"Stack.Base",
"BX"
};
return mem_to_str[ mem ];
}
}
namespace Register
{
ct u8 Mask_Imme = 0b00000111;
ct u8 Mask_Left = 0b00111000;
ct u8 Mask_Right = 0b00000111;
#define D_Opcodes \
D_Entry( AL ) \
D_Entry( CL ) \
D_Entry( DL ) \
D_Entry( BL ) \
D_Entry( AH ) \
D_Entry( CH ) \
D_Entry( DH ) \
D_Entry( BH ) \
D_Entry( AX ) \
D_Entry( CX ) \
D_Entry( DX ) \
D_Entry( BX ) \
D_Entry( SP ) \
D_Entry( BP ) \
D_Entry( SI ) \
D_Entry( DI ) \
D_Entry( AL ) \
D_Entry( CL ) \
D_Entry( DL ) \
D_Entry( BL ) \
D_Entry( AH ) \
D_Entry( CH ) \
D_Entry( DH ) \
D_Entry( BH ) \
D_Entry( AX ) \
D_Entry( CX ) \
D_Entry( DX ) \
D_Entry( BX ) \
D_Entry( SP ) \
D_Entry( BP ) \
D_Entry( SI ) \
D_Entry( DI ) \
enum Type : u8
{
@ -251,7 +279,7 @@ namespace Register
#undef D_Entry
};
return Type_To_Meumonic[ type + Width * 7 + 1 ];
return Type_To_Meumonic[ type + Width * ( 7 + 1 ) ];
}
char const* intuitive( Type type, u8 Width )
@ -259,38 +287,77 @@ namespace Register
static char const*
Type_To_Intuitive[ Num ] =
{
"A.Low",
"C.Low",
"D.Low",
"B.Low",
"A.High",
"C.High",
"D.High",
"B.High",
"A.16",
"C.16",
"D.16",
"B.16",
"Accumulator.Low",
"Count.Low",
"Data.Low",
"Base.Low",
"Accumulator.High",
"Count.High",
"Data.High",
"Base.High",
"Accumulator.16",
"Count.16",
"Data.16",
"Base.16",
"Stack.Pointer",
"Stack.Base",
"Source.Index",
"Destination.Index",
};
return Type_To_Intuitive[ type + Width * 7 + 1 ];
return Type_To_Intuitive[ type + Width * ( 7 + 1 ) ];
}
}
// 8086 Instructions are 1 to 6 bytes in length.
struct Octal
{
u8 Low : 3;
u8 High : 3;
u8 Dir : 1;
u8 Write : 1;
operator u8()
{
return * cast( u8*, this);
}
};
struct POD_Instruction
{
u8 Byte_1;
u8 Byte_2;
u8 Byte_3;
u8 Byte_4;
u8 Byte_5;
u8 Byte_6;
// 8086 Instructions are 1 to 6 bytes in length.
union
{
u8* Ptr;
u8 Byte[6];
Octal Instr;
struct
{
u8 Pad[2];
u16_Split Disp;
u16_Split Data;
}
EffAddr;
struct
{
u8 Pad[1];
u16_Split Data;
}
Imme;
struct
{
u8 Pad;
u16_Split Data;
}
Addr;
};
// If directly referencing blob data:
// Part of next instruction, do not use as stratch memory.
u16 Pad;
};
@ -299,120 +366,232 @@ struct Instruction : public POD_Instruction
using Code = Op::Code;
using Direction = Field::Direction;
using Mode = Field::Mode;
using Memory = Field::Memory;
using Width = Field::Width;
using Reg = Register::Type;
inline
Direction direction()
Direction get_direction()
{
Direction
direction = cast(Direction, Byte_1 & Field::Mask_Dir);
Direction direction = cast(Direction, Byte[0] & Field::Mask_Dir);
return direction;
}
inline
Mode mode()
Mode get_mode()
{
Mode mode = cast( Mode, Byte_2 & Field::Mask_Mode );
Mode mode = cast( Mode, Byte[1] & Field::Mask_Mode );
return mode;
}
inline
Code opcode()
Code get_opcode( u8 mask )
{
Op::Code
opcode = cast( Op::Code, Byte_1 & Op::Mask );
Op::Code opcode = cast( Op::Code, Byte[0] & mask );
return opcode;
}
inline
Reg operand_left()
Width get_width( u8 mask )
{
Width width = cast( Width, Byte[0] & mask );
return width;
}
inline
Reg mode_operand_left_reg()
{
u8
operand = Byte_2 & Register::Mask_Left;
operand = Byte[1] & Register::Mask_Left;
operand >>= 3;
return cast(Reg, operand);
}
inline
Reg operand_right()
Reg mode_operand_right_reg()
{
u8 operand = Byte_2 & Register::Mask_Right;
u8 operand = Byte[1] & Register::Mask_Right;
return cast( Reg, operand );
}
inline
Width width()
{
Width width = cast( Width, Byte_1 & Field::Mask_Width );
return width;
}
void dissassemble( zpl_string* result_out )
forceinline
void dissassemble_mode( char const*& str_operand, Width& width, u8& length )
{
using namespace Field;
using namespace Op;
using namespace Register;
Direction dir = direction();
Width width_val = width();
switch ( get_mode() )
{
case Mode_Mem:
{
Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
char const* opcode_str = Op::meumonic( opcode() );
char const* direction_str = Field::str_direction( dir );
char const* width_str = Field::str_width( width_val );
char const* mode_str = Field::str_mode( mode() );
char const* operand_left_str = Register::meumonic( operand_left(), width_val );
char const* operand_right_str = Register::meumonic( operand_right(), width_val );
length += 2;
char
binary_string[9];
binary_string[8] = '\0';
if ( operand_right == Add_Direct )
{
u16 address = EffAddr.Disp;
#if Build_Debug
str_binary( binary_string, opcode() );
zpl_printf("\nOpcode : %s : %s", binary_string, opcode_str);
str_operand = string_format( "[ %u ]", address );
}
else
{
str_operand = str_memory( operand_right );
}
}
break;
str_binary( binary_string, dir );
zpl_printf("\nDirection : %s : %s", binary_string, direction_str);
case Mode_Mem8:
{
Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
str_binary( binary_string, width_val );
zpl_printf("\nWidth : %s : %s", binary_string, width_str);
length += 1;
str_binary( binary_string, mode() );
zpl_printf("\nMode : %s : %s", binary_string, mode_str);
str_operand = string_format( "[ %s + %u ]", str_memory( operand_right), EffAddr.Disp.Low );
}
break;
str_binary( binary_string, operand_left() );
zpl_printf("\nOperand : %s : %s", binary_string, operand_left_str);
case Mode_Mem16:
{
length += 2;
str_binary( binary_string, operand_right() );
zpl_printf("\nOperand EA : %s : %s", binary_string, operand_right_str);
#endif
Memory operand_right = cast( Memory, Byte[1] & Mask_Memory );
u16 address = EffAddr.Disp;
if ( result_out == nullptr )
return;
str_operand = string_format( "[ %s + %u ]", str_memory( operand_right), address );
}
break;
if ( * result_out == nullptr )
* result_out = zpl_string_make_reserve( allocator, zpl_kilobytes(1) );
case Mode_Reg:
str_operand = Register::meumonic( mode_operand_right_reg(), width );
break;
}
}
zpl_string assembly = zpl_string_make_reserve( allocator, 32);
u8 dissassemble( zpl_string* result_out )
{
using namespace Field;
using namespace Op;
using namespace Register;
assembly = zpl_string_sprintf( allocator, assembly, zpl_kilobytes(1) - 1, "\n%s %s, %s"
, opcode_str
, dir == Dir_Src ? operand_right_str : operand_left_str
, dir == Dir_Src ? operand_left_str : operand_right_str
u8 length = 1;
zpl_string assembly = string_make( 32);
Code code = get_opcode( Op::Mask );
Direction dir = get_direction();
char const* str_operand_left = nullptr;
char const* str_operand_right = nullptr;
const u8 code_low = Byte[0] & Op::Mask_Low;
const u8 code_high = Byte[0] & Op::Mask_High;
const u8 sig_imme = Byte[0] & Op::Mask_Imme;
if ( get_opcode( Op::Mask_Low ) == mov_Im_R )
{
Width width = get_width( Mask_Width_Imme );
Reg reg = cast(Reg, Byte[0] & Register::Mask_Right );
u16 immediate = width == Width_Byte ?
Imme.Data.Low : Imme.Data;
str_operand_left = Register::meumonic( reg, width );
str_operand_right = string_format( "%u", immediate );
}
else
{
switch ( code )
{
#pragma region mov
case mov_RM_R:
{
length++;
Width width = get_width( Mask_Width );
str_operand_left = Register::meumonic( mode_operand_left_reg(), width );
dissassemble_mode( str_operand_right, width, length );
}
break;
case mov_Im_RM:
{
Width width = get_width( Mask_Width_Imme );
Memory operand_left = cast( Memory, Byte[1] & Mask_Memory );
u16 address = EffAddr.Disp;
u16 immediate = width == Width_Byte ?
EffAddr.Data.Low : EffAddr.Data;
dissassemble_mode( str_operand_left, width, length );
str_operand_right = string_format( "%u", immediate );
}
break;
case mov_M_Acc:
{
Width width = get_width( Mask_Width );
u16 address = width == Width_Byte ?
Addr.Data.Low : Addr.Data;
str_operand_left = Register::meumonic( Reg::AX, Width_Word );
str_operand_right = string_format( "%u", address );
}
break;
case mov_Acc_M:
{
Width width = get_width( Mask_Width );
u16 address = width == Width_Byte ?
Addr.Data.Low : Addr.Data;
str_operand_right = string_format( "%u", address );
str_operand_left = Register::meumonic( Reg::AX, Width_Word );
}
break;
case mov_RM_SR:
{
}
break;
case mov_SR_RM:
{
}
break;
#pragma endregion mov
}
}
assembly = string_format( assembly, 32, "\n%s %s, %s"
// opcode operand_right, operand_left
, Op::meumonic( code)
, str_operand_right
, str_operand_left
);
* result_out = zpl_string_append( * result_out, assembly );
if ( result_out == nullptr )
return length;
if ( * result_out == nullptr )
* result_out = string_make( zpl_kilobytes(1) );
* result_out = string_append( * result_out, assembly );
#if Build_Debug
zpl_printf("\n\nAssembly: %s\n\n", assembly);
#endif
return length;
}
};
@ -426,14 +605,14 @@ namespace Tests
Instruction
mock; // mov CX, BX
mock.Byte_1 = mov_88 | Dir_Src | Field::Width_Word;
mock.Byte_2 = Field::Mode_Reg | effective_address(BX) | CX;
mock.Byte[0] = mov_RM_R | Dir_Src | Field::Width_Word;
mock.Byte[1] = Field::Mode_Reg | offset_left_reg(BX) | CX;
zpl_printf("\n\nAttempting Mock Instruction: mov CX, BX");
print_nl();
print_as_binary( & mock.Byte_1, 1, " " );
print_as_binary( & mock.Byte_2, 1, " " );
print_as_binary( & mock.Byte[0], 1, " " );
print_as_binary( & mock.Byte[1], 1, " " );
print_nl();
zpl_string dissasembly = nullptr;
@ -441,12 +620,12 @@ namespace Tests
mock.dissassemble( & dissasembly);
}
void try_blob_single_instruction()
void try_blob_single_move()
{
zpl_printf("\n\nAttempting to read blob: listing_0037_single_register_mov");
zpl_file_contents
blob = zpl_file_read_contents( allocator, false, "tests/listing_0037_single_register_mov" );
blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0037_single_register_mov" );
if (blob.data == nullptr )
return;
@ -462,17 +641,17 @@ namespace Tests
Instruction
instr;
instr.Byte_1 = data[0];
instr.Byte_2 = data[1];
instr.Byte[0] = data[0];
instr.Byte[1] = data[1];
instr.dissassemble( & dissasembly);
}
void try_blob_many_instructions()
void try_blob_many_moves()
{
zpl_printf("\n\nAttempting to read blob: listing_0038_many_register_mov");
zpl_file_contents
blob = zpl_file_read_contents( allocator, false, "tests/listing_0038_many_register_mov" );
blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0038_many_register_mov" );
if (blob.data == nullptr )
return;
@ -484,14 +663,14 @@ namespace Tests
print_as_binary( data, left, " " );
print_nl();
zpl_string dissasembly = zpl_string_make( allocator, "bits 16\n");
zpl_string dissasembly = string_make( "bits 16\n");
while ( left )
{
Instruction
instr;
instr.Byte_1 = data[0];
instr.Byte_2 = data[1];
instr.Byte[0] = data[0];
instr.Byte[1] = data[1];
instr.dissassemble( & dissasembly);
data += 2;
@ -509,7 +688,47 @@ namespace Tests
);
}
#undef allocator
void try_blob_more_moves()
{
zpl_printf("\n\nAttempting to read blob: listing_0039_more_movs");
zpl_file_contents
blob = zpl_file_read_contents( g_allocator, false, "tests/listing_0039_more_movs" );
if (blob.data == nullptr )
return;
u32 left = blob.size;
u8* data = cast( u8*, blob.data );
print_nl();
print_as_binary( data, left, " " );
print_nl();
zpl_string dissasembly = string_make( "bits 16\n");
while ( left )
{
Instruction
instr;
instr.Ptr = data;
u8 length = instr.dissassemble( & dissasembly);
data += length;
left -= length;
}
zpl_printf("\n\nDissassemlby:\n%s", dissasembly);
dissasembly = zpl_string_append_fmt( dissasembly, "\n" );
zpl_printf("\n\nSaving to file");
zpl_file_write_contents("tests/listing_0039_more_movs.asm.out.asm"
, dissasembly
, zpl_string_length(dissasembly)
, nullptr
);
}
}
@ -519,16 +738,14 @@ int main()
setup();
zpl_f64 start = zpl_time_rel();
f64 start = zpl_time_rel();
#if 0
Tests::try_mock_instruction();
Tests::try_blob_single_instruction();
#endif
Tests::try_blob_many_instructions();
// Tests::try_blob_single_move();
// Tests::try_blob_many_moves();
Tests::try_blob_more_moves();
zpl_f64 end = zpl_time_rel();
zpl_f64 ms = (end - start) * 100;
f64 end = zpl_time_rel();
f64 ms = (end - start) * 100;
printf("\n\nElapsed Time: %lf ms", ms);
printf("\n\n");

View File

@ -1,12 +1,12 @@
bits 16
mov CX, BX
mov DH, CH
mov CH, AH
mov DX, BX
mov SI, BX
mov BX, DI
mov CL, DL
mov DH, DH
mov AL, CL
mov CH, CH
mov BX, AX
mov BX, SI
mov SP, DI

Binary file not shown.

View File

@ -0,0 +1,47 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ========================================================================
; ========================================================================
; LISTING 39
; ========================================================================
bits 16
; Register-to-register
mov si, bx
mov dh, al
; 8-bit immediate-to-register
mov cl, 12
mov ch, -12
; 16-bit immediate-to-register
mov cx, 12
mov cx, -12
mov dx, 3948
mov dx, -3948
; Source address calculation
mov al, [bx + si]
mov bx, [bp + di]
mov dx, [bp]
; Source address calculation plus 8-bit displacement
mov ah, [bx + si + 4]
; Source address calculation plus 16-bit displacement
mov al, [bx + si + 4999]
; Dest address calculation
mov [bx + di], cx
mov [bp + si], cl
mov [bp], ch

View File

@ -0,0 +1,43 @@
bits 16
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),
INVALID VALUE PROVIDED (null),

Binary file not shown.

View File

@ -0,0 +1,38 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ========================================================================
; ========================================================================
; LISTING 40
; ========================================================================
bits 16
; Signed displacements
mov ax, [bx + di - 37]
mov [si - 300], cx
mov dx, [bx - 32]
; Explicit sizes
mov [bp + di], byte 7
mov [di + 901], word 347
; Direct address
mov bp, [5]
mov bx, [3458]
; Memory-to-accumulator test
mov ax, [2555]
mov ax, [16]
; Accumulator-to-memory test
mov [2554], ax
mov [15], ax