Emulating %defstr in earlier versions of NASM - nasm

Is there a way to emulate %defstr in NASM versions earlier than 2.03, preferably 0.99.06? More particularly, I want this macro to work:
%macro name 1
%defstr __namestr__ %1
%1: db __namestr__, 0
%endmacro
so that name hello would be equivalent to hello: db 'hello', 0. It already works in NASM 2.03 and later. I need it in a portable NASM include file, and requiring the user to upgrade NASM is not an option.
This doesn't work, it emits a literal %1 (2 bytes) + NUL.
%macro name 1
%1: db '%1', 0
%endif
NASM 0.99.06 .. NASM 2.02 documentation says that a workaround can be created using a multi-line macro (for converting tokens to a string literal), but it doesn't specify how. The full excerpt:
The `%!<env>' directive makes it possible to read the value of an
environment variable at assembly time. This could, for example, be
used to store the contents of an environment variable into a string,
which could be used at some other point in your code.
For example, suppose that you have an environment variable `FOO',
and you want the contents of `FOO' to be embedded in your program.
You could do that as follows:
%define FOO %!FOO
%define quote '
tmpstr db quote FOO quote
At the time of writing, this will generate an "unterminated string"
warning at the time of defining "quote", and it will add a space
before and after the string that is read in. I was unable to find a
simple workaround (although a workaround can be created using a
multi-line macro), so I believe that you will need to either learn
how to create more complex macros, or allow for the extra spaces if
you make use of this feature in that way.

The preprocessor macro %defstr is “smart” enough and escapes, for instance, any occurrence of string delimiter characters.
Therefore it’s different from a %define simply surrounding the argument with quotes.
However, in your specific case, since the first and only parameter to the name macro must also be suitable label, you do not have to worry about problematic characters.
Taking the excerpt from the documentation as inspiration and after having verified that %+ was already documented in 0.98.x, you can write something like:
%define quote '
%macro name 1
%1: db quote %+%1%+ quote, 0
%endmacro
I did only check this with NASM version 2.15.05, so no guarantee that this indeed works with 0.99.06.

Related

Printing strings in LC-3 assembly language (super noob)

Super noob here. I'm doing a "hello world" type program in LC-3 assembly language and I simply don't know how to print more than one string to the console. I need 4 strings on separate lines that are my class, name, project and goodbye. Right now all I can seem to print in the class.
.ORIG x3000
LOOP LEA R0, CLASS
LD R1, NAME
LD R2, PROJECT
LD R3, GOODBYE
PUTS
HALT
CLASS .STRINGZ "CS101\n"
NAME .STRINGZ "JOHN\n"
...
.END
How would I get the other 3 to print? Thanks!
The Z in .STRINGZ means zero terminated. That is you have declared separate strings. If you want to print them all, you need to invoke PUTS multiple times. Alternatively, make it a single string with embedded newlines. Then you can print the whole thing in one go.

Whats this line mean? (system:call getfreediskex)

System::Call '${sysGetDiskFreeSpaceEx}(r0,.,,.r1)'
If i'm right, r0: directoryname, free bytes, number of bytes, number oof free bytes, but what actually means the r0,.,.,r1?
Thx for the help!
${...} is a define so when you want to know how some things work then the first thing you should do is to find out what the define does: !error "${sysGetDiskFreeSpaceEx}" will print !error: kernel32::GetDiskFreeSpaceEx(t, *l, *l, *l) i
In the System readme you will find this nugget:
PARAMS, RETURN and OPTIONS can be repeated many times in one Get/Call
line. When repeating, a lot can be omitted, and only what you wish to
change can be used. Type, source and/or destination can be omitted for
each parameter, even the return value. Options can be added or
removed. This allows you to define function prototypes and save on
some typing.
So ${sysGetDiskFreeSpaceEx} is a prototype that specifies the parameter count and types but it does not specify parameter source and destination.
What is the parameter syntax?
The parameters list is separated by commas. Each parameter is combined
of three values: type, source and destination. Type can be an integer,
a string, etc. Source, which is the source of the parameter value, can
be a NSIS register ($0, $1, $INSTDIR), the NSIS stack, a concrete
value (5, "test", etc.) or nothing (null). Destination, which is the
destination of the parameter value after the call returns, can be a
NSIS register, the NSIS stack or nothing which means no output is
required. Either one of source or destination can also be a dot (`.')
if it is not needed.
We can now expand the entire call !error 'System::Call "${sysGetDiskFreeSpaceEx}(r0,.,,.r1)"' and this gives us !error: System::Call 'kernel32::GetDiskFreeSpaceEx(t, *l, *l, *l) i(r0,.,,.r1)'
If we merge the repeated parameter definitions we get kernel32::GetDiskFreeSpaceEx(tr0, *l., *l, *l.r1)i.
So parameter 1 is a string (LPTSTR on MSDN) with the source r0 (NSIS register $0).
Parameter 2 and 3 have no source and no destination, only parameter 2 uses a . (dot) but the end result is the same; no input and no output. The only important part here is *l so the system plugin knows how large the parameter is.
The final parameter is a pointer (*) to a 64 bit number (l) with no input (.) and we request the output to be stored in $1 (r1).
The system plugin calls the native Windows API so it is often useful to look at MSDN to see what it has to say about the function you are calling.
Given that $0..$9 and $R0..$R9 are NSIS registers, the notation r0 -> r9 (resp. R10..R19 or also R0..R9) is used by the System plugin to specify the $0..$9 (resp. $R0..$R9) registers as a source and / or a destination with system API or other dll function calls.
Either one of source or destination can also be a dot (.) if it is not needed.
Look for the "Calling functions" and "Available sources and destinations" sections in the system plugin documentation.

String in Assembly

What does .string do in assembly?
In an inline asm call in c, I wrote
.string \"Hello World\"
1) Can somebody give me an overview of how .string works?
2) Somehow that value gets saved in %esi. Why?
3) How can I append a return carriage on the end? \n doesn't work
.string is an assembler directive in GAS similar to .long, .int, or .byte. All it does is create and initialize memory for you to use in your program. The .string directive will automatically null-terminate the string with [\0] for you. In this case, the assembler is allocating space for 14 characters in 14 contiguous bytes of memory. If you were to look at the memory, you would see this:
["][H][e][l][l][o][ ][W][o][r][l][d]["][\0]
Except in hexadecimal rather than characters. I'm not sure how or why %esi points to the string (it's either an assembler setting I'm not familiar with or has been set that way on a line of code you're not showing us). What it means is that %esi "points" to the first byte of the string - in this case the first ["]. You can use the %esi register to loop through the bytes using an offset (%esi + 5 would be [o]) or by incrementing the register itself.
To add a newline you might want to try \x0D\x0A instead of \n.
It just emits a sequence of characters into the appropriate code/data section. See this and this (they use .ascii, though).
Show us the code.
Try \\n or \12 or \xa.

Delphi - ADO query and FillChar generates errors

I have the following code:
var wqry:TAdoQuery;
...
FillChar(wSpaces,cSpacesAfter,' ');
try
wqry := TADOQuery.Create(nil);//here the error
wqry.Connection:=...
cSpacesAfter is a constant and has the value 1035. wSpaces is a local string variable. The problem is that I receive the following error when TAdoQuery is created
even it is in french, I believe you got the idea.....
If I comment the FillChar code, everything works ok. I have the usual compiler directives, nothing special. I'm using Delphi 7.
Can someone tell me what is wrong with that code?
The troublesome code is most likely this one
FillChar(wSpaces,cSpacesAfter,' ');
I'm assuming that wSpaces is of string type. A string variable is in fact nothing more than a pointer to the data structure that holds the string. You don't need to use pointer syntax because the compiler takes care of that for you.
So what this code does is overwrite the variable holding that pointer with 4 space characters and then write 1031 more spaces over the top of whatever follows the variable. In short you will completely corrupt your memory. That would explain why the FillChar works but the very next line of code dies a painful and dramatic death.
If your string indeed had space for 1035 characters your could instead write:
FillChar(wSpaces[1], cSpacesAfter, ' ');
However, if may be more idiomatic to write:
wSpaces := StringOfChar(' ', cSpacesAfter);
FillChar procedure fills out a section of storage Buffer with the same byte or character FillValue FillCount times.
It is principally used to initialise arrays of numbers. It can be used to initialise records and strings, but care should be used to avoid overwriting length fields. StringOfChar is best for filling out strings to the same character.
Are you sure wSpaces has the size enough to fit all of cSpacesAfter you write to it?

How to store binary data in a Lua string

I needed to create a custom file format with embedded meta information. Instead of whipping up my own format I decide to just use Lua.
texture
{
format=GL_LUMINANCE_ALPHA;
type=GL_UNSIGNED_BYTE;
width=256;
height=128;
pixels=[[
<binary-data-here>]];
}
texture is a function that takes a table as its sole argument. It then looks up the various parameters by name in the table and forwards the call on to a C++ routine. Nothing out of the ordinary I hope.
Occasionally the files fail to parse with the following error:
my_file.lua:8: unexpected symbol near ']'
What's going on here?
Is there a better way to store binary data in Lua?
Update
It turns out that storing binary data is a Lua string is non-trivial. But it is possible when taking care with 3 sequences.
Long-format-string-literals cannot have an embedded closing-long-bracket (]], ]=], etc).
This one is pretty obvious.
Long-format-string-literals cannot end with something like ]== which would match the chosen closing-long-bracket.
This one is more subtle. Luckily the script will fail to compile if done wrong.
The data cannot embed \n or \r.
Lua's built in line-end processing messes these up. This problem is much more subtle. The script will compile fine but it will yield the wrong data. 0x13 => 0x10, 0x1013 => 0x10, etc.
To get around these limitations I split the binary data up on \r, \n, then pick a long-bracket that works, finally emit Lua that concats the various parts back together. I used a script that does this for me.
input: XXXX\nXX]]XX\r\nXX]]XX]=
texture
{
--other fields omitted
pixels= '' ..
[[XXXX]] ..
'\n' ..
[=[XX]]XX]=] ..
'\r\n' ..
[==[XX]]XX]=]==];
}
Lua is able to encode most characters in long bracket format including nulls. However, Lua opens the script file in text mode and this causes some problems. On my Windows system the following characters have problems:
Char code(s) Problem
-------------- -------------------------------
13 (CR) Is translated to 10 (LF)
13 10 (CR LF) Is translated to 10 (LF)
26 (EOF) Causes "unfinished long string near '<eof>'"
If you are not using windows than these may not cause problems, but there may be different text-mode based problems.
I was only able to produce the error you received by encoding multiple close brackets:
a=[[
]]] --> a.lua:2: unexpected symbol near ']'
But, this was easily fixed with the following:
a=[==[
]]==]
The binary data needs to be encoded into printable characters. The simplest method for decoding purposes would be to use C-like escape sequences for all bytes. For example, hex bytes 13 41 42 1E would be encoded as '\19\65\66\30'. Of course, then the encoded data is three to four times larger than the source binary.
Alternatively, you could use something like Base64, but that would have to be decoded at runtime instead of relying on the Lua interpreter. Personally, I'd probably go the Base64 route. There are Lua examples of Base64 encoding and decoding.
Another alternative would be have two files. Use a well defined image format file (e.g. TGA) that is pointed to by a separate Lua script with the additional metadata. If you don't want two files to move around then they could be combined in an archive.

Resources