summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-11-08 20:01:11 -0800
committerH. Peter Anvin <hpa@zytor.com>2007-11-08 20:01:11 -0800
commit8781cb0d0054620ccc3670292fe1ab8ccb5bc1c2 (patch)
treee38d967d1017bf43d84b76a37a9f7acf510657ac
parent52bd38b899ed03dee25aea931c0908354b4ae6a6 (diff)
downloadnasm-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.c69
-rw-r--r--test/local.asm18
2 files changed, 51 insertions, 36 deletions
diff --git a/preproc.c b/preproc.c
index 9bc6f711..ddfa3da2 100644
--- a/preproc.c
+++ b/preproc.c
@@ -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