Skip to content

Commit 4ebd802

Browse files
committed
merge dev for version v1.3.1
1 parent bdebc69 commit 4ebd802

20 files changed

+2548
-68
lines changed

Changelog

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1+
version 1.3.1-release (2022-11-10)
2+
3+
- added support for all shift instructions shr/shl/sar/sal as well as all
4+
their respective operand encodings
5+
6+
- fixed operand encoding for xchg intruction when using the return register
7+
8+
- fixed xabort instruction missing 8-bit immediate value
9+
10+
- fixed xbegin instruction rel32 offset value
11+
112
version 1.3.1-rc.3 (2022-08-17)
213

314
- fixed a bug which caused a segmentation fault when writing to a file via
4-
the -P switch
15+
the -P switch
516

617
version 1.3.1-rc.2 (2022-08-09)
718

819
- added four encodings for {vmovdqu, vmovupd} xmmN {xmmN,m/128}
9-
and two for {vmovdqu, vmovupd} m/128, xmmN
20+
and two for {vmovdqu, vmovupd} m/128, xmmN
1021

1122
version 1.3.1-rc.1 (2022-08-09)
1223

Makefile.am

+6-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ include_HEADERS = src/assemblyline.h
7070
# 3. Programs may need to be changed, recompiled, and relinked in order to use the new version. Bump current, set revision and age to 0.
7171

7272
# in short, if only patch from configure.ac is bumped, bump the middle number below. If more is changed, read the above
73-
libassemblyline_la_LDFLAGS = -version-info 3:3:2
73+
libassemblyline_la_LDFLAGS = -version-info 3:4:2
7474
##############################################################################################
7575
##############################################################################################
7676
############################### BINS ##############################################
@@ -180,6 +180,7 @@ TEST_ASM = \
180180
test/bextr.asm \
181181
test/bzhi.asm \
182182
test/clc.asm \
183+
test/clflush.asm \
183184
test/cmp.asm \
184185
test/cpuid.asm \
185186
test/high_low_xmm.asm \
@@ -198,7 +199,6 @@ TEST_ASM = \
198199
test/mulx.asm \
199200
test/neg.asm \
200201
test/negative_mem_disp.asm \
201-
test/new_instruction.asm \
202202
test/no_ptr.asm \
203203
test/no_operand.asm \
204204
test/nop.asm \
@@ -229,6 +229,8 @@ TEST_ASM = \
229229
test/rdtscp.asm \
230230
test/ror.asm \
231231
test/rorx.asm \
232+
test/sal.asm \
233+
test/sar.asm \
232234
test/sarx.asm \
233235
test/sbb.asm \
234236
test/setc.asm \
@@ -252,6 +254,8 @@ TEST_ASM = \
252254
test/vmovupd.asm \
253255
test/vperm2i128.asm \
254256
test/vsubpd.asm \
257+
test/xabort.asm \
258+
test/xchg.asm \
255259
test/xor.asm \
256260
test/zero_byte_rbp.asm
257261

configure.ac

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Process this file with autoconf to produce a configure script.
33

44
AC_PREREQ([2.69])
5-
AC_INIT([assemblyline],[1.3.1-rc.3],[[email protected]])
5+
AC_INIT([assemblyline],[1.3.1],[[email protected]])
66
AC_CONFIG_HEADERS([config.h])
77
AC_CONFIG_SRCDIR([src/assemblyline.c])
88
AC_CONFIG_AUX_DIR([build-aux])

src/assembler.c

+1
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ static unsigned int assemble_instr(struct instr *instruc, unsigned char ptr[]) {
251251

252252
case ib:
253253
instruc->reduced_imm = true;
254+
instruc->cons &= MAX_UNSIGNED_8BIT;
254255
break;
255256

256257
case rd:

src/common.h

+4
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@
183183
#define SMART_MOV_IMM 0b00010
184184
#define GET_EN 0b11111100000000000000000
185185

186+
// check instruction attributes
187+
#define TYPE(key, instr_type) (INSTR_TABLE[(key)].type == (instr_type))
188+
#define NAME(key, instr_name) (INSTR_TABLE[(key)].name == (instr_name))
189+
186190
// various length nop instructions
187191
#define NOP 0x90
188192
#define NOP2 0x66, 0x90

src/encoder.c

+24-19
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ as well process any offsets or immediate operands*/
2929
*/
3030
static void auto_set_byte(struct instr *instrc) {
3131
// instructions that only supports a single 8-bit operand
32-
if (INSTR_TABLE[instrc->key].type == BYTE_OPD) {
32+
if (TYPE(instrc->key, BYTE_OPD)) {
3333
instrc->keyword.is_byte = true;
3434
instrc->op_offset = 0;
3535
}
@@ -66,7 +66,7 @@ void encode_offset(struct instr *instrc) {
6666
(instrc->opd[1].reg & MODE_MASK) == noext8)
6767
return;
6868
// set opcode offset
69-
if (INSTR_TABLE[instrc->key].type != CONTROL_FLOW && !instrc->keyword.is_byte)
69+
if (!TYPE(instrc->key, CONTROL_FLOW) && !instrc->keyword.is_byte)
7070
instrc->op_offset = get_opcode_offset(instrc);
7171
}
7272

@@ -184,16 +184,19 @@ static int encode_special_opd(struct instr *instrc, int m, int i) {
184184
int encode_operands(struct instr *instrc) {
185185

186186
// xchg instruction with RM operand encoding using rax or al register
187-
if (INSTR_TABLE[instrc->key].name == xchg &&
188-
INSTR_TABLE[instrc->key].encode_operand == RM) {
189-
if ((reg64 & instrc->opd[0].reg) && (REG_MASK & instrc->opd[0].reg) == al) {
187+
if (NAME(instrc->key, xchg) && !instrc->mem_disp) {
188+
if ((MODE_MASK & instrc->opd[0].reg) > noext8 &&
189+
(REG_MASK & instrc->opd[0].reg) == al) {
190+
// swap operands
191+
struct operand temp = instrc->opd[1];
192+
instrc->opd[1] = instrc->opd[0];
193+
instrc->opd[0] = temp;
190194
instrc->key++;
191-
instrc->rd_offset = instrc->opd[1].reg & VALUE_MASK;
192-
} else if ((reg64 & instrc->opd[1].reg) &&
195+
} else if ((MODE_MASK & instrc->opd[1].reg) > noext8 &&
193196
(REG_MASK & instrc->opd[1].reg) == al) {
194197
instrc->key++;
195-
instrc->rd_offset = instrc->opd[0].reg & VALUE_MASK;
196198
}
199+
instrc->rd_offset = instrc->opd[0].reg & VALUE_MASK;
197200
}
198201
// set 'byte' keyword
199202
if (instrc->mem_disp)
@@ -302,36 +305,38 @@ static void encode_imm_operation(struct instr *instrc) {
302305
}
303306

304307
void encode_imm(struct instr *instrc) {
308+
// change op offset based on reg and imm size
309+
if (!instrc->imm)
310+
return;
305311
// ignore imm value if instruction is a branch type
306-
if ((INSTR_TABLE[instrc->key].type == SHIFT && instrc->cons == 1) ||
307-
INSTR_TABLE[instrc->key].type == CONTROL_FLOW)
312+
if ((TYPE(instrc->key, SHIFT) && instrc->cons == 1) ||
313+
TYPE(instrc->key, CONTROL_FLOW)) {
308314
instrc->imm = false;
315+
return;
316+
}
309317
// used for shift instruction with an 8bit imm rather than one
310-
else if (INSTR_TABLE[instrc->key].type == SHIFT && instrc->cons != 1)
318+
if (TYPE(instrc->key, SHIFT) && instrc->cons != 1) {
311319
instrc->key++;
312-
// change op offset based on reg and imm size
313-
if (!instrc->imm)
314320
return;
321+
}
315322
// return register used for imm instructions sub, sbb, add, adc
316-
if (INSTR_TABLE[instrc->key].type == OPERATION)
323+
if (TYPE(instrc->key, OPERATION))
317324
encode_imm_operation(instrc);
318325
// vector shift instrctions
319326
if ((instrc->opd[0].reg & MODE_MASK) == mmx64)
320327
instrc->reduced_imm = true;
321328
// special case for test
322-
else if (instrc->op_offset == 1 &&
323-
INSTR_TABLE[instrc->key].type == PAD_ALWAYS) {
329+
else if (instrc->op_offset == 1 && TYPE(instrc->key, PAD_ALWAYS)) {
324330
if (IN_RANGE(instrc->cons, NEG32BIT + 1, NEG64BIT)) {
325331
DO_NOT_PAD(instrc->cons, instrc->reduced_imm, MAX_UNSIGNED_32BIT);
326332
}
327333
if ((instrc->opd[0].reg & REG_MASK) == al)
328334
instrc->key++;
329335
// 16 to 64 bit register and 8 bit immediate combination
330-
} else if (instrc->op_offset == 1 &&
331-
INSTR_TABLE[instrc->key].type != DATA_TRANSFER) {
336+
} else if (instrc->op_offset == 1 && !TYPE(instrc->key, DATA_TRANSFER)) {
332337
encode_imm_non_data_transfer(instrc);
333338
// special condition for to mov instruction
334-
} else if (INSTR_TABLE[instrc->key].type == DATA_TRANSFER)
339+
} else if (TYPE(instrc->key, DATA_TRANSFER))
335340
encode_imm_data_transfer(instrc);
336341
// mask all bits except for the most significant byte
337342
if ((instrc->opd[0].reg & MODE_MASK) < reg32) {

src/enums.h

+1
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ typedef enum {
222222
ret,
223223
ror,
224224
rorx,
225+
sal,
225226
sar,
226227
sarx,
227228
sbb,

src/instruction_data.h

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ struct instr {
102102
bool reduced_imm : 1;
103103
unsigned long cons;
104104
bool zero_byte : 1;
105+
// when operand is a memory reference M
105106
bool mem_disp : 1;
106107
bool mem_value : 1;
107108
bool is_sib_const : 1;

src/instructions.c

+13-8
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ const struct instr_table INSTR_TABLE[] = {
163163
{{'\0'}, movq, {NA, mv}, MR, VECTOR, NA, NA, 5, {0x66, REX, 0x0f, 0xd6, REG}},
164164
{{'\0'}, movq, {NA, rv}, MR, VECTOR, NA, NA, 5, {0x66, REX, 0x0f, 0x7e, REG}},
165165
{{'\0'}, movq, {vm, vv}, RM, VECTOR, NA, NA, 5, {0xf3, REX, 0x0f, 0x7e, REG}},
166-
{"movzx", movzx, {rr, rm}, RM, OTHER, NA, NA, 4, {REX, 0x0f, 0xb6, REG}},
166+
{"movzx", movzx, {rr, rm}, RM, DATA_TRANSFER, NA, NA, 4, {REX, 0x0f, 0xb6, REG}},
167167
{"mulpd", mulpd, {NA, vv}, RM, VECTOR, NA, NA, 5, {0x66, REX, 0x0f, 0x59, REG}},
168168
{"mulx", mulx, {rrr, rrm}, RVM, VECTOR_EXT, NA, NA, 3, {VEX(NDD,LZ,XF2,X0F38,W0_W1), 0xf6, REG}},
169169
{"neg", neg, {r, m}, M, OTHER, 1, 3, 3, {REX, 0xf6, REG}},
@@ -239,8 +239,12 @@ const struct instr_table INSTR_TABLE[] = {
239239
{"ror", ror, {NA, ri}, M, SHIFT, NA, 1, 4, {REX, 0xd1, REG, ib}},
240240
{{'\0'}, ror, {NA, NA}, M, SHIFT, NA, 1, 4, {REX, 0xc1, REG, ib}},
241241
{"rorx", rorx, {rri, rmi}, RM, VECTOR_EXT, NA, NA, 4, {VEX(NNN,LZ,XF2,X0F3A,W0_W1), 0xf0, REG, ib}},
242+
{"sal", sal, {mi, ri}, M, SHIFT, 1, 4, 4, {REX, 0xd0, REG, ib}},
243+
{{'\0'}, sal, {NA, NA}, M, SHIFT, 1, 4, 4, {REX, 0xc0, REG, ib}},
244+
{{'\0'}, sal, {mr, rr}, M, SHIFT, 1, 4, 3, {REX, 0xd2, REG}},
242245
{"sar", sar, {mi, ri}, M, SHIFT, 1, 7, 4, {REX, 0xd0, REG, ib}},
243246
{{'\0'}, sar, {NA, NA}, M, SHIFT, 1, 7, 4, {REX, 0xc0, REG, ib}},
247+
{{'\0'}, sar, {mr, rr}, M, SHIFT, 1, 7, 3, {REX, 0xd2, REG}},
244248
{"sarx", sarx, {rrr, rmr}, RMV, VECTOR_EXT, NA, NA, 3, {VEX(NDS,LZ,XF3,X0F38,W0_W1), 0xf7, REG}},
245249
{"sbb", sbb, {rr, mr}, MR, OPERATION, 1, NA, 3, {REX, 0x18, REG}},
246250
{{'\0'}, sbb, {NA, rm}, RM, OPERATION, 1, NA, 3, {REX, 0x1a, REG}},
@@ -277,14 +281,15 @@ const struct instr_table INSTR_TABLE[] = {
277281
{"sets", sets, {r, m}, M, BYTE_OPD, NA, 0, 4, {REX, 0x0f, 0x98, REG}},
278282
{"setz", setz, {r, m}, M, BYTE_OPD, NA, 0, 4, {REX, 0x0f, 0x94, REG}},
279283
{"sfence", sfence, {n, n}, NA, OTHER, NA, NA, 3, {0x0f, 0xae, 0xf8}},
280-
{"shl", shl, {NA, ri}, M, SHIFT, NA, 4, 4, {REX, 0xd1, REG, ib}},
281-
{{'\0'}, shl, {NA, NA}, M, SHIFT, NA, 4, 4, {REX, 0xc1, REG, ib}},
284+
{"shl", shl, {mi, ri}, M, SHIFT, 1, 4, 4, {REX, 0xd0, REG, ib}},
285+
{{'\0'}, shl, {NA, NA}, M, SHIFT, 1, 4, 4, {REX, 0xc0, REG, ib}},
286+
{{'\0'}, shl, {mr, rr}, M, SHIFT, 1, 4, 3, {REX, 0xd2, REG}},
282287
{"shld", shld, {rri, mri}, MR, OTHER, NA, NA, 5, {REX, 0x0f, 0xa4, REG, ib}},
283288
{{'\0'}, shld, {rrr, mrr}, MR, OTHER, NA, NA, 4, {REX, 0x0f, 0xa5, REG}},
284289
{"shlx", shlx, {rrr, rmr}, RMV, VECTOR_EXT, NA, NA, 3, {VEX(NDS,LZ,X66,X0F38,W0_W1), 0xf7, REG}},
285-
{"shr", shr, {NA, ri}, M, SHIFT, 1, 5, 4, {REX, 0xbe, REG, ib}},
286-
{{'\0'}, shr, {NA, NA}, M, SHIFT, NA, 5, 4, {REX, 0xc1, REG, ib}},
287-
{{'\0'}, shr, {NA, rr}, M, SHIFT, NA, 5, 3, {REX, 0xd3, REG}},
290+
{"shr", shr, {mi, ri}, M, SHIFT, 1, 5, 4, {REX, 0xbe, REG, ib}},
291+
{{'\0'}, shr, {NA, NA}, M, SHIFT, 1, 5, 4, {REX, 0xc0, REG, ib}},
292+
{{'\0'}, shr, {mr, rr}, M, SHIFT, 1, 5, 3, {REX, 0xd2, REG}},
288293
{"shrd", shrd, {mri, rri}, MR, OTHER, 2, NA, 4, {REX, 0x0f, 0xa9, REG}},
289294
{"shrx", shrx, {rrr, rmr}, RMV, VECTOR_EXT, NA, NA, 3, {VEX(NDS,LZ,XF2,X0F38,W0_W1), 0xf7, REG}},
290295
{"sub", sub, {rr, mr}, MR, OPERATION, 1, NA, 3, {REX, 0x28, REG}},
@@ -347,8 +352,8 @@ const struct instr_table INSTR_TABLE[] = {
347352
{"vpxor", vpxor, {yym, yyy}, RVM, VECTOR_AVX, NA, NA, 3, {VEX(NDS,B256,X66,X0F,WIG), 0xef, REG}},
348353
{{'\0'}, vpxor, {vvm, vvv}, RVM, VECTOR_AVX, NA, NA, 3, {VEX(NDS,B128,X66,X0F,WIG), 0xef, REG}},
349354
{"vsubpd", vsubpd, {yym, yyy}, RVM, VECTOR_AVX, NA, NA, 3, {VEX(NDS,B256,X66,X0F,WIG), 0x5c, REG}},
350-
{"xabort", xabort, {n, n}, I, CONTROL_FLOW, NA, NA, 2, {0xc6, 0xf8}},
351-
{"xbegin", xbegin, {n, n}, NA, CONTROL_FLOW, NA, NA, 2, {0xc7, 0xf8}},
355+
{"xabort", xabort, {n, n}, I, OTHER, NA, NA, 3, {0xc6, 0xf8, ib}},
356+
{"xbegin", xbegin, {n, n}, NA, OTHER, NA, NA, 2, {0xc7, 0xf8}},
352357
{"xchg", xchg, {rr, rm}, RM, DATA_TRANSFER, 1, NA, 3, {REX, 0x86, REG}},
353358
{{'\0'}, xchg, {NA, NA}, I, DATA_TRANSFER, NA, NA, 2, {REX, 0x90+rd}},
354359
{"xor", xor, {rr, mr}, MR, OPERATION, 1, NA, 3, {REX, 0x30, REG}},

src/parser.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ static void all_opd_str_to_reg(struct instr *instr_data) {
6060
* tokenize and parse @param filtered_asm_str to fill in @param instr_data
6161
*/
6262
static int line_to_instr(struct instr *instr_data, char *filtered_asm_str) {
63+
// back up instruction for error checking
64+
char asm_str[MAX_LINE_LEN];
65+
strncpy(asm_str, filtered_asm_str, MAX_LINE_LEN);
6366
// default mod displacement value r/m is register
6467
instr_data->mod_disp = MOD24;
6568
// clear the least significant bit
@@ -86,9 +89,8 @@ static int line_to_instr(struct instr *instr_data, char *filtered_asm_str) {
8689
// convert instruction string to enum representation
8790
instr_data->key = str_to_instr_key(instr_data->instruction, opd_format);
8891
FAIL_IF_VAR(instr_data->key == INSTR_ERROR,
89-
"unsupported or illegal instruction: %s\n",
90-
instr_data->instruction);
91-
if (instr_data->imm && INSTR_TABLE[instr_data->key].type == CONTROL_FLOW) {
92+
"unsupported or illegal instruction: %s\n", asm_str);
93+
if (instr_data->imm && TYPE(instr_data->key, CONTROL_FLOW)) {
9294
if (IN_RANGE(instr_data->cons, NEG80_32BIT, MAX_UNSIGNED_32BIT) ||
9395
(instr_data->cons <= MAX_SIGNED_8BIT && !instr_data->keyword.is_long))
9496
instr_data->keyword.is_short = true;
@@ -109,7 +111,7 @@ static int line_to_instr(struct instr *instr_data, char *filtered_asm_str) {
109111
"Invalid register for instruction: %s\n",
110112
instr_data->instruction);
111113
// force jump immediate to 32 bits
112-
if (INSTR_TABLE[instr_data->key].type == CONTROL_FLOW &&
114+
if (TYPE(instr_data->key, CONTROL_FLOW) &&
113115
IN_RANGE(instr_data->cons, NEG32BIT + 1, NEG64BIT))
114116
instr_data->cons &= MAX_UNSIGNED_32BIT;
115117
// encode for the reg_hex value and op_offset for instruction
@@ -124,8 +126,7 @@ static int line_to_instr(struct instr *instr_data, char *filtered_asm_str) {
124126
}
125127
// special case for push instruction with immediate
126128
// (used push imm16 or imm32 when immediate is greater than 0x7f)
127-
if (INSTR_TABLE[instr_data->key].name == push &&
128-
instr_data->cons > MAX_SIGNED_8BIT)
129+
if (NAME(instr_data->key, push) && instr_data->cons > MAX_SIGNED_8BIT)
129130
instr_data->key++;
130131
return EXIT_SUCCESS;
131132
}

0 commit comments

Comments
 (0)