diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-11-08 20:01:11 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2007-11-08 20:01:11 -0800 |
commit | 8781cb0d0054620ccc3670292fe1ab8ccb5bc1c2 (patch) | |
tree | e38d967d1017bf43d84b76a37a9f7acf510657ac | |
parent | 52bd38b899ed03dee25aea931c0908354b4ae6a6 (diff) | |
download | nasm-8781cb0d0054620ccc3670292fe1ab8ccb5bc1c2.tar.gz |
BR 1828103: Fix %arg and %local
Correct the implementation of %arg and %local.
It's questionable how much they make sense for 64-bit mode; even in
32-bit mode one normally make references off the stack pointer instead
of the base pointer (frame pointer), but that requires keeping track
of the stack pointer offset.
-rw-r--r-- | preproc.c | 69 | ||||
-rw-r--r-- | test/local.asm | 18 |
2 files changed, 51 insertions, 36 deletions
@@ -300,10 +300,6 @@ static int is_condition(enum preproc_token arg) * then jam in the equivalent NASM directive into the input stream. */ -#ifndef MAX -# define MAX(a,b) ( ((a) > (b)) ? (a) : (b)) -#endif - enum { TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI, TM_IFNDEF, TM_INCLUDE, TM_LOCAL @@ -317,7 +313,7 @@ static const char * const tasm_directives[] = { static int StackSize = 4; static char *StackPointer = "ebp"; static int ArgOffset = 8; -static int LocalOffset = 4; +static int LocalOffset = 0; static Context *cstk; static Include *istk; @@ -1718,6 +1714,18 @@ static void undef_smacro(Context *ctx, const char *mname) } } +/* + * Decode a size directive + */ +static int parse_size(const char *str) { + static const char *size_names[] = + { "byte", "dword", "oword", "qword", "tword", "word" }; + static const int sizes[] = + { 0, 1, 4, 16, 8, 10, 2 }; + + return sizes[bsii(str, size_names, elements(size_names))+1]; +} + /** * find and process preprocessor directive in passed line * Find out if a line contains a preprocessor directive, and deal @@ -1813,7 +1821,7 @@ static int do_directive(Token * tline) StackSize = 4; StackPointer = "ebp"; ArgOffset = 8; - LocalOffset = 4; + LocalOffset = 0; } else if (nasm_stricmp(tline->text, "large") == 0) { /* All subsequent ARG directives are for a 16-bit stack, * far function call. @@ -1821,7 +1829,7 @@ static int do_directive(Token * tline) StackSize = 2; StackPointer = "bp"; ArgOffset = 4; - LocalOffset = 2; + LocalOffset = 0; } else if (nasm_stricmp(tline->text, "small") == 0) { /* All subsequent ARG directives are for a 16-bit stack, * far function call. We don't support near functions. @@ -1829,7 +1837,7 @@ static int do_directive(Token * tline) StackSize = 2; StackPointer = "bp"; ArgOffset = 6; - LocalOffset = 2; + LocalOffset = 0; } else { error(ERR_NONFATAL, "`%%stacksize' invalid size type"); free_tlist(origline); @@ -1879,17 +1887,8 @@ static int do_directive(Token * tline) /* Allow macro expansion of type parameter */ tt = tokenize(tline->text); tt = expand_smacro(tt); - if (nasm_stricmp(tt->text, "byte") == 0) { - size = MAX(StackSize, 1); - } else if (nasm_stricmp(tt->text, "word") == 0) { - size = MAX(StackSize, 2); - } else if (nasm_stricmp(tt->text, "dword") == 0) { - size = MAX(StackSize, 4); - } else if (nasm_stricmp(tt->text, "qword") == 0) { - size = MAX(StackSize, 8); - } else if (nasm_stricmp(tt->text, "tword") == 0) { - size = MAX(StackSize, 10); - } else { + size = parse_size(tt->text); + if (!size) { error(ERR_NONFATAL, "Invalid size type for `%%arg' missing directive"); free_tlist(tt); @@ -1898,6 +1897,9 @@ static int do_directive(Token * tline) } free_tlist(tt); + /* Round up to even stack slots */ + size = (size+StackSize-1) & ~(StackSize-1); + /* Now define the macro for the argument */ snprintf(directive, sizeof(directive), "%%define %s (%s+%d)", arg, StackPointer, offset); @@ -1908,8 +1910,8 @@ static int do_directive(Token * tline) tline = tline->next; if (tline && tline->type == TOK_WHITESPACE) tline = tline->next; - } - while (tline && tline->type == TOK_OTHER && tline->text[0] == ','); + } while (tline && tline->type == TOK_OTHER && tline->text[0] == ','); + ArgOffset = offset; free_tlist(origline); return DIRECTIVE_FOUND; @@ -1960,17 +1962,8 @@ static int do_directive(Token * tline) /* Allow macro expansion of type parameter */ tt = tokenize(tline->text); tt = expand_smacro(tt); - if (nasm_stricmp(tt->text, "byte") == 0) { - size = MAX(StackSize, 1); - } else if (nasm_stricmp(tt->text, "word") == 0) { - size = MAX(StackSize, 2); - } else if (nasm_stricmp(tt->text, "dword") == 0) { - size = MAX(StackSize, 4); - } else if (nasm_stricmp(tt->text, "qword") == 0) { - size = MAX(StackSize, 8); - } else if (nasm_stricmp(tt->text, "tword") == 0) { - size = MAX(StackSize, 10); - } else { + size = parse_size(tt->text); + if (!size) { error(ERR_NONFATAL, "Invalid size type for `%%local' missing directive"); free_tlist(tt); @@ -1979,11 +1972,15 @@ static int do_directive(Token * tline) } free_tlist(tt); - /* Now define the macro for the argument */ + /* Round up to even stack slots */ + size = (size+StackSize-1) & ~(StackSize-1); + + offset += size; /* Negative offset, increment before */ + + /* Now define the macro for the argument */ snprintf(directive, sizeof(directive), "%%define %s (%s-%d)", local, StackPointer, offset); do_directive(tokenize(directive)); - offset += size; /* Now define the assign to setup the enter_c macro correctly */ snprintf(directive, sizeof(directive), @@ -1994,8 +1991,8 @@ static int do_directive(Token * tline) tline = tline->next; if (tline && tline->type == TOK_WHITESPACE) tline = tline->next; - } - while (tline && tline->type == TOK_OTHER && tline->text[0] == ','); + } while (tline && tline->type == TOK_OTHER && tline->text[0] == ','); + LocalOffset = offset; free_tlist(origline); return DIRECTIVE_FOUND; diff --git a/test/local.asm b/test/local.asm new file mode 100644 index 00000000..64a0e59a --- /dev/null +++ b/test/local.asm @@ -0,0 +1,18 @@ + bits 32 + +%push bluttan + +%define %$localsize 0 + +%stacksize flat +%local l1:qword, l2:dword, l3:dword, l4:qword +%arg a1:qword, a2:dword, a3:dword, a4:qword + + mov eax,[a1] + mov ebx,[a2] + mov ecx,[a3] + mov edx,[a4] + mov [l1],eax + mov [l2],ebx + mov [l3],ecx + mov [l4],edx |