initialized string in MASM struture - string

In C I have this structure
struct frame
{
int whidth;
int height;
char* name;
};
I want the same in MASM
frame STRUCT
name
whidth DWORD ?
height DWORD ?
name
frame ENDS
for the name I can write ",name DWORD ?" and affect by an adress'string at runtime
but I want to initilized it.
I try this :
c1 db "big",0
c2 db "medium",0
c3 db "small",0
Frames frame <100, 50, c1>,<80, 30, c2>,<50, 20, c3>
It's not working !
I also try this
frame STRUCT
name DB <> ?
whidth DWORD ?
height DWORD ?
name
frame ENDS
don't work !
and this makes me strings of equal length filled with spaces ...
Frames frame <100, 50, "big">,<80, 30, "medium">,<50, 20, "small">
What's the right syntax?

You chose to omit some pretty important information from your question; the actual error message(s) you were getting.
The error messages I get for the DWORD ? variant are:
error A2008: syntax error : name
error A2036: too many initial values for structure
So let's look up error A2008:
syntax error :
A token at the current location caused a syntax error.
One of the following may have occurred:
A dot prefix was added to or omitted from a directive.
A reserved word (such as C or SIZE) was used as an identifier.
An instruction was used that was not available with the current processor or coprocessor selection.
A comparison run-time operator (such as ==) was used in a conditional assembly statement instead of a relational operator (such as EQ).
An instruction or directive was given too few operands.
An obsolete directive was used.
A few of these talk about directives, so let's open the list of MASM directives. Sure enough, NAME is listed as a directive. This means that you can't use NAME for your own symbols, since that falls under "A reserved word (such as C or SIZE) was used as an identifier". And because reserved words are case-insensitive that also rules out use of name for your own symbols.
So now you have two options:
Call the field something other than name.
If you don't need the NAME directive in your program you can remove its reserved word status using option nokeyword:<name>. You can then freely call your struct field name.
As far as initializing the field is concerned; the variant with DWORD ? would be the one most closely matching the C code, since only the address of the string gets stored in the struct, just like in the C code.

I found this "obvious" solution thanks for your help.
frame STRUCT
name DWORD ?
whidth DWORD ?
height DWORD ?
name
frame ENDS
c1 db "big",0
c2 db "medium",0
c3 db "small",0
Frames DWORD c1
DWORD 100
DWORD 50
DWORD c2
DWORD 80
DWORD 30
DWORD c3
DWORD 50
DWORD 20

Related

How to get the location in the compressed data - zlib

When I save the 'state of uncompression', I also need to save:
"location in the compressed data, which is both a byte offset and bit offset within that byte".
After a reboot, along with inflateSetDictionary(), I call inflatePrime() as below, "to feed the bits from the byte at the compressed data offset".
inflatePrime ( , streamBits, streamCurrentPos)
Both APIs return Z_OK, but params to inflatePrime(), I am bit uncertain.
This is how I gathered them:
typedef struct state_of_uncompression
{
uInt streamCurrentPos; // Missing this, tried the output from unzGetCurrentFileZStreamPos64()
int streamBits; // from : stream.data_type, after clearing bits 8,7,6: stream.data_type & (~0x1C0)
Byte dictionary_buf[32768]; // from : inflateGetDictionary()
uInt dictLength; // from : inflateGetDictionary();
uint64_t output_wrt_offset // got this already.
} uncompression_state_info;
So after the reboot, the plan is to recontinue the uncompression, but inflate() returns Z_STREAM_END inside unzReadCurrentFile(), as if, inflate() doesn't know where to restart from.
Thanks appreciate any feedback.
The third argument to inflatePrime() is not a position. It is the actual bits to insert, which you need to get from the compressed data. You use fseek() or lseek() to go to the byte offset in the file, where you saved that offset as part of your entry point information. You get that byte, which advances the file pointer to the next byte, and shift down by the number of bits you are not providing, i.e. 8 minus the second argument. That's the third argument. The second argument is always in 1..7. If there are no bits to insert, then you don't call inflatePrime(), and just leave the file pointer where it is to begin inflating.
The position in your state should be a 64-bit value, not a 32-bit value as you currently have it.

Trouble With Reading In A String With A Subroutine In LC3

So I believe that the way I store the string works. I am just having some issues passing the String out of the subroutine. I heard that in order to pass something out of a subroutine you need to store it in R1 but I can't get it to store into my WORD array
.orig x3000
AND R1,R1,0
LEA R0,PROMPT
PUTS
JSR GETS
ST R1,WORD
LEA R0,WORD
PUTS
halt
; ---------Data Area-------------
WORD .blkw 20
PROMPT .stringz "Enter String: "
; -------------------------------
GETS LEA R1,MEMORYBLOCK ; saves the address of the storage memory block
loop GETC ; input character -> r0
PUTC ; r0 -> console
; always points at the next available block
LD R2,EMPTY ; check for
ADD R2,R2,R0 ; end of line
BRz finish
LD R2,COUNTDOWN
ADD R2,R2,#-1
BRz finish
ST R2,COUNTDOWN
STR R0,R1,#0 ; r0 -> ( memory address stored in r1 + 0 )
ADD R1,R1,#1 ; increments the memory pointer so that it
BR loop
finish LEA R1,MEMORYBLOCK
RET
; ----Subroutine Data Area-------
EMPTY .fill xfff6
COUNTDOWN .fill #10
MEMORYBLOCK .BLKW 20
; -------------------------------
.end
The biggest problem here is the concept of "returning a string". What you're actually doing at the end of GETS is returning the memory address at which the string starts. When you then store this into WORD in the calling function, you are storing the memory address of the first byte of the string that was input (i.e. the memory address of MEMORYBLOCK) into the first byte of WORD. You aren't copying the entire string from MEMORYBLOCK into WORD.
The easiest "fix" for what you're trying to do would be to change
LEA R0,WORD
to
LD R0,WORD
and then for good measure:
WORD .blkw 20
to
WORD .fill 0
as now you're just using it to store a single value (i.e. the memory address of MEMORYBLOCK).
However, at this point you haven't made a copy of the string. If you want to do this, then you will need to make a loop whereby you walk through MEMORYBLOCK and copy each byte to WORD instead.
The final, cheaper, way to do this is to just use MEMORYBLOCK directly from the calling function. It's not really any less valid in a program of this size, unless there's project requirements that ask otherwise.

How to implement GetThreadContext in Linux/Unix?

GetThreadContext is a Windows API.
BOOL WINAPI GetThreadContext(
_In_ HANDLE hThread,
_Inout_ LPCONTEXT lpContext
);
I wonder that how to implement it in linux.
How to retrieves the register information of the specified thread in Linux?
Like this:
pthread_create(thread_id, ...);
...
func(thread_id, reg_info)
{
//get the reg_info by thread_id.
??
}
A Linux-specific way of getting thread info is to use get_thread_area(). From the get_thread_area() man page:
get_thread_area() returns an entry in the current thread's Thread Local Storage (TLS) array. The index of the entry corresponds to the value of u_info->entry_number, passed in by the user. If the value is in bounds, get_thread_area() copies the corresponding TLS entry into the area pointed to by u_info.
But, if you want to read the register value you need to take help of inline assembly. Fox example, to retrieve the value of esp you can use the following inline assembly:
unsigned sp;
__asm __volatile("movl %%esp, %0" : "=r" (sp));
return sp;
In this way, you can extract ebp, eip etc. Hope this will help!

getting to an ELF file information

ok...
so im suppose to write a program that prints all of the sections name in an elf file using only mmap (thats not important...)
so what i did so far is this -
maped the file into the stat structure =
map_start = mmap(0, fd_stat.st_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0)) <0 )
casted it into the write format from the starting point i got =
header = (Elf32_Ehdr *) map_start;
gotten the section header offset from the file =
secoff = header->e_shoff;
now - i know i need to go to the map_start+secoff location - that will give me the section table, and the sh_name will give me an index for the string table...
how to i go to the sting table?
how is it represented?
how do i use it? and is the value in sh_name the index in the string table (if it is represented as an array) , or an offset..
anyway - lets say i want to print the first two section's name - how do i do it givven the code i wrote above
help please?
header = (Elf32_Ehdr *) map_start;
secoff = header->e_shoff;
This is probably wrong. Unless the Elf32_Ehdr structure is explicitly declared __attribute__((packed)), the compiler will eventually insert padding between the members of the structure, so sizeof(Elf32_Ehdr) != (the actual size of an ELF header section). Why not simply use the libelf accessor functions instead?
Update: if you're not allowed to use accessor functions, you'll have to do something like this:
Elf32_Ehdr hdr;
memcpy(&hdr.e_ident, map_start + 0, EI_NIDENT);
memcpy(&hdr.e.type, map_start + 0 + sizeof(Elf32_half), sizeof(Elf32_Half));
et cetera.

Is it possible to store pointers in shared memory without using offsets?

When using shared memory, each process may mmap the shared region into a different area of its respective address space. This means that when storing pointers within the shared region, you need to store them as offsets of the start of the shared region. Unfortunately, this complicates use of atomic instructions (e.g. if you're trying to write a lock free algorithm). For example, say you have a bunch of reference counted nodes in shared memory, created by a single writer. The writer periodically atomically updates a pointer 'p' to point to a valid node with positive reference count. Readers want to atomically write to 'p' because it points to the beginning of a node (a struct) whose first element is a reference count. Since p always points to a valid node, incrementing the ref count is safe, and makes it safe to dereference 'p' and access other members. However, this all only works when everything is in the same address space. If the nodes and the 'p' pointer are stored in shared memory, then clients suffer a race condition:
x = read p
y = x + offset
Increment refcount at y
During step 2, p may change and x may no longer point to a valid node. The only workaround I can think of is somehow forcing all processes to agree on where to map the shared memory, so that real pointers rather than offsets can be stored in the mmap'd region. Is there any way to do that? I see MAP_FIXED in the mmap documentation, but I don't know how I could pick an address that would be safe.
Edit: Using inline assembly and the 'lock' prefix on x86 maybe it's possible to build a "increment ptr X with offset Y by value Z"? Equivalent options on other architectures? Haven't written a lot of assembly, don't know if the needed instructions exist.
On low level the x86 atomic inctruction can do all this tree steps at once:
x = read p
y = x + offset Increment
refcount at y
//
mov edi, Destination
mov edx, DataOffset
mov ecx, NewData
#Repeat:
mov eax, [edi + edx] //load OldData
//Here you can also increment eax and save to [edi + edx]
lock cmpxchg dword ptr [edi + edx], ecx
jnz #Repeat
//
This is trivial on a UNIX system; just use the shared memory functions:
shgmet, shmat, shmctl, shmdt
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmat() attaches the shared memory
segment identified by shmid to the
address space of the calling process.
The attaching address is specified by
shmaddr with one of the following
criteria:
If shmaddr is NULL, the system chooses
a suitable (unused) address at which
to attach the segment.
Just specify your own address here; e.g. 0x20000000000
If you shmget() using the same key and size in every process, you will get the same shared memory segment. If you shmat() at the same address, the virtual addresses will be the same in all processes. The kernel doesn't care what address range you use, as long as it doesn't conflict with wherever it normally assigns things. (If you leave out the address, you can see the general region that it likes to put things; also, check addresses on the stack and returned from malloc() / new[] .)
On Linux, make sure root sets SHMMAX in /proc/sys/kernel/shmmax to a large enough number to accommodate your shared memory segments (default is 32MB).
As for atomic operations, you can get them all from the Linux kernel source, e.g.
include/asm-x86/atomic_64.h
/*
* Make sure gcc doesn't try to be clever and move things around
* on us. We need to use _exactly_ the address the user gave us,
* not some alias that contains the same information.
*/
typedef struct {
int counter;
} atomic_t;
/**
* atomic_read - read atomic variable
* #v: pointer of type atomic_t
*
* Atomically reads the value of #v.
*/
#define atomic_read(v) ((v)->counter)
/**
* atomic_set - set atomic variable
* #v: pointer of type atomic_t
* #i: required value
*
* Atomically sets the value of #v to #i.
*/
#define atomic_set(v, i) (((v)->counter) = (i))
/**
* atomic_add - add integer to atomic variable
* #i: integer value to add
* #v: pointer of type atomic_t
*
* Atomically adds #i to #v.
*/
static inline void atomic_add(int i, atomic_t *v)
{
asm volatile(LOCK_PREFIX "addl %1,%0"
: "=m" (v->counter)
: "ir" (i), "m" (v->counter));
}
64-bit version:
typedef struct {
long counter;
} atomic64_t;
/**
* atomic64_add - add integer to atomic64 variable
* #i: integer value to add
* #v: pointer to type atomic64_t
*
* Atomically adds #i to #v.
*/
static inline void atomic64_add(long i, atomic64_t *v)
{
asm volatile(LOCK_PREFIX "addq %1,%0"
: "=m" (v->counter)
: "er" (i), "m" (v->counter));
}
We have code that's similar to your problem description. We use a memory-mapped file, offsets, and file locking. We haven't found an alternative.
You shouldn't be afraid to make up an address at random, because the kernel will just reject addresses it doesn't like (ones that conflict). See my shmat() answer above, using 0x20000000000
With mmap:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
If addr is not NULL, then the kernel
takes it as a hint about where to
place the mapping; on Linux, the
mapping will be created at the next
higher page boundary. The address of
the new mapping is returned as the
result of the call.
The flags argument determines whether
updates to the mapping are visible to
other processes mapping the same
region, and whether updates are
carried through to the underlying
file. This behavior is determined by
including exactly one of the following
values in flags:
MAP_SHARED Share this mapping.
Updates to the mapping are visible to
other processes that map this
file, and are carried through to the
underlying file. The file may not
actually be updated until msync(2) or
munmap() is called.
ERRORS
EINVAL We don’t like addr, length, or
offset (e.g., they are too large, or
not aligned on a page boundary).
Adding the offset to the pointer does not create the potential for a race, it already exists. Since at least neither ARM nor x86 can atomically read a pointer then access the memory it refers to you need to protect the pointer access with a lock regardless of whether you add an offset.

Resources