Why does this sentence eliminate the "unreferenced function argument warning"? - c

in SDCC Compiler User Guide I read the following:
void to_buffer( unsigned char c )
{
c; // to avoid warning: unreferenced function argument
__asm
; save used registers here.
; If we were still using r2,r3 we would have to push them here.
; if( head != (unsigned char)(tail-1) )
mov a,_tail
dec a
xrl a,_head
; we could do an ANL a,#0x0f here to use a smaller buffer (see below)
jz t_b_end$
;
; buf[ head++ ] = c;
mov a,dpl ; dpl holds lower byte of function argument
mov dpl,_head ; buf is 0x100 byte aligned so head can be used directly
mov dph,#(_buf>>8)
movx #dptr,a
inc _head
; we could do an ANL _head,#0x0f here to use a smaller buffer (see above)
t_b_end$:
; restore used registers here
__endasm;
}
I don't understand what does the sentence "c; // to avoid warning: unreferenced function argument" mean, is it a special usage of SDCC? Or a special usage of C language?

Compilers tend to warn you if you have an incoming function parameter that you don't use. In your case, c; is a void operation to access the variable and to avoid the warning. It is similar to
int func(char c)
{
(void)c;
//c is never used in the function
}
FWIW, in gcc, to enable the warning, -Wunused-parameter option is used. (enabled in -Wextra)

Related

C99: compiler optimizations when accessing global variables and aliased memory pointers

I'm writing C code for an embedded system. In this system, there are memory mapped registers at some fixed address in the memory map, and of course some RAM where my data segment / heap is.
I'm finding problems generating optimal code when my code is intermixing accesses to global variables in the data segment and accesses to hardware registers. This is a simplified snippet:
#include <stdint.h>
uint32_t * const restrict HWREGS = 0x20000;
struct {
uint32_t a, b;
} Context;
void example(void) {
Context.a = 123;
HWREGS[0x1234] = 5;
Context.b = Context.a;
}
This is the code generated on x86 (see also on godbolt):
example:
mov DWORD PTR Context[rip], 123
mov DWORD PTR ds:149712, 5
mov eax, DWORD PTR Context[rip]
mov DWORD PTR Context[rip+4], eax
ret
As you can see, after having written the hardware register, Context.a is reloaded from RAM before being stored into Context.b. This doesn't make sense because Context is at a different memory address than HWREGS. In other words, the memory pointed by HWREGS and the memory pointed by &Context do not alias, but it looks like there is not way to tell that to the compiler.
If I change HWREGS definition as this:
extern uint32_t * const restrict HWREGS;
that is, I hide the fixed memory address to the compiler, I get this:
example:
mov rax, QWORD PTR HWREGS[rip]
mov DWORD PTR [rax+18640], 5
movabs rax, 528280977531
mov QWORD PTR Context[rip], rax
ret
Context:
.zero 8
Now the two writes to Context are optimized (even coalesced to a single write), but on the other hand the access to the hardware register does not happen anymore with a direct memory access but it goes through a pointer indirection.
Is there a way to obtain optimal code here? I would like GCC to know that HWREGS is at a fixed memory address and at the same time to tell it that it does not alias Context.
If you want to avoid compilers reloading regularly values from a memory region (possibly due to aliasing), then the best is not to use global variables, or at least not to use direct accesses to global variables. The register keyword seems ignored for global variables (especially here on HWREGS) for both GCC and Clang. Using the restrict keyword on function parameters solves this problem:
#include <stdint.h>
uint32_t * const HWREGS = 0x20000;
struct Context {
uint32_t a, b;
} context;
static inline void exampleWithLocals(uint32_t* restrict localRegs, struct Context* restrict localContext) {
localContext->a = 123;
localRegs[0x1234] = 5;
localContext->b = localContext->a;
}
void example() {
exampleWithLocals(HWREGS, &context);
}
Here is the result (see also on godbolt):
example:
movabs rax, 528280977531
mov DWORD PTR ds:149712, 5
mov QWORD PTR context[rip], rax
ret
context:
.zero 8
Please note that the strict aliasing rule do not help in this case since the type of read/written variables/fields is always uint32_t.
Besides this, based on its name, the variable HWREGS looks like a hardware register. Please note that it should be put volatile so that compiler do not keep it to registers nor perform any similar optimization (like assuming the pointed value is left unchanged if the code do not change it).

Wrong function address

Here’s the code:
__declspec ( naked ) void nseel_asm_assign(void)
{
__asm
{
fld qword ptr [eax]
fstp qword ptr [ebx]
}
}
__declspec ( naked ) void nseel_asm_assign_end(void) {}
The code that consumes them crashes. The debugger shows the addresses are OK, e.g.
&nseel_asm_assign 0x0f45e4a0 {vis_avs.dll!nseel_asm_assign(void)} void(*)()
&nseel_asm_assign_end 0x0f45e4b0 {vis_avs.dll!nseel_asm_assign_end(void)} void(*)()
However, when the address of these functions is taken by the actual C code not by the debugger, it stops being correct and the consuming code crashes because the size is negative:
fn 0x0f455056 {vis_avs.dll!_nseel_asm_assign} void(*)()
fn_e 0x0f45295f {vis_avs.dll!_nseel_asm_assign_end} void(*)()
The underscored functions contain just a single instruction, e.g. jmp nseel_asm_assign
How do I get the addresses of the real functions, without the underscore?
Update: in case you wondering why I wrote code like this, it wasn’t me, it’s third party, and it worked just fine when built with VC++ 6.0.
Here’s how to get the real address.
static void* unwrapJumpAddress( void *f )
{
const uint8_t* pb = (const uint8_t*)f;
if( *pb == 0xE9 ) // JMP: http://felixcloutier.com/x86/JMP.html
{
const int offset = *(const int*)( pb + 1 );
// The jump offset is relative to the start of the next instruction.
// This JMP takes 5 bytes.
return (void*)( pb + 5 + offset );
}
return f;
}

INT 13 Extension Read in C

i can use extended read functions of bios int 13h well from assembly,
with the below code
; *************************************************************************
; Setup DISK ADDRESS PACKET
; *************************************************************************
jmp strtRead
DAPACK :
db 010h ; Packet Size
db 0 ; Always 0
blkcnt:
dw 1 ; Sectors Count
db_add :
dw 07e00h ; Transfer Offset
dw 0 ; Transfer Segment
d_lba :
dd 1 ; Starting LBA(0 - n)
dd 0 ; Bios 48 bit LBA
; *************************************************************************
; Start Reading Sectors using INT13 Func 42
; *************************************************************************
strtRead:
mov si, OFFSET DAPACK; Load DPACK offset to SI
mov ah, 042h ; Function 42h
mov dl, 080h ; Drive ID
int 013h; Call INT13h
i want to convert this to be a c callable function but i have no idea about how to transfer the parameters from c to asm like drive id , sectors count, buffer segment:offset .... etc.
i am using msvc and masm and working with nothing except bios functions.
can anyone help ?!!
update :
i have tried the below function but always nothing loaded into the buffer ??
void read_sector()
{
static unsigned char currentMBR[512] = { 0 };
struct disk_packet //needed for int13 42h
{
byte size_pack; //size of packet must be 16 or 16+
byte reserved1; //reserved
byte no_of_blocks; //nof blocks for transfer
byte reserved2; //reserved
word offset; //offset address
word segment; //segment address
dword lba1;
dword lba2;
} disk_pack;
disk_pack.size_pack = 16; //set size to 16
disk_pack.no_of_blocks = 1; //1 block ie read one sector
disk_pack.reserved1 = 0; //reserved word
disk_pack.reserved2 = 0; //reserved word
disk_pack.segment = 0; //segment of buffer
disk_pack.offset = (word)&currentMBR[0]; //offset of buffer
disk_pack.lba1 = 0; //lba first 32 bits
disk_pack.lba2 = 0; //last 32 bit address
_asm
{
mov dl, 080h;
mov[disk_pack.segment], ds;
mov si, disk_pack;
mov ah, 42h;
int 13h
; jc NoError; //No error, ignore error code
; mov bError, ah; // Error, get the error code
NoError:
}
}
Sorry to post this as "answer"; I want to post this as "comment" but it is too long...
Different compilers have a different syntax of inline assembly. This means that the correct syntax of the following lines:
mov[disk_pack.segment], ds;
mov si, disk_pack;
... depends on the compiler used. Unfortunately I do not use 16-bit C compilers so I cannot help you in this point.
The next thing I see in your program is the following one:
disk_pack.segment = 0; //segment of buffer
disk_pack.offset = (word)&currentMBR[0]; //offset of buffer
With a 99% chance this will lead to a problem. Instead I would to the following:
struct disk_packet //needed for int13 42h
{
byte size_pack;
byte reserved;
word no_of_blocks; // note that this is 16-bit!
void far *data; // <- This line is the main change!
dword lba1;
dword lba2;
} disk_pack;
...
disk_pack.size_pack = 16;
disk_pack.no_of_blocks = 1;
disk_pack.reserved = 0;
disk_pack.data = &currentMBR[0]; // also note the change here
disk_pack.lba1 = 0;
disk_pack.lba2 = 0;
...
Note that some compilers name the keyword "_far" or "__far" instead of "far".
A third problem is that some (buggy) BIOSes require ES to be equal to the segment value from the disk_pack and a fourth one is that many compilers require the inline assembly code not to modify any registers (AX, CX and DX is normally OK).
These two could be solved the following way:
push ds;
push es;
push si;
mov dl, 080h;
// TODO here: Set ds:si to disk_pack in a compiler-specific way
mov es,[si+6];
mov ah, 42h;
int 13h;
...
pop si;
pop es;
pop ds;
In my opinion the "#pragma pack" should not be neccessary because all elements in the structure are propperly aligned.

How do I get info from the stack, using inline assembly, to program in c?

I have a task to do and I'm asking for some help. (on simple c lang')
What I need to do?
I need to check every command on the main c program (using interrupt num 1) and printing a message only if the next command is the same procedure that was sent earlier to the stack, by some other procedure.
What I want to do?
I want to take info from the stack, using inline assembley, and put it on a variable that can be compare on c program itself after returnning to c. (volatile)
This is the program:
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
typedef void (*FUN_PTR)(void);
void interrupt (*Int1Save) (void); //pointer to interrupt num 1//
volatile FUN_PTR our_func;
char *str2;
void interrupt my_inter (void) //New interrupt//
{volatile FUN_PTR next_command;
asm { PUSH BP
MOV BP,SP
PUSH AX
PUSH BX
PUSH ES
MOV ES,[BP+4]
MOV BX,[BP+2]
MOV AX,ES:[BX]
MOV word ptr next_command,AX
POP ES
POP BX
POP AX
pop BP}
if (our_func==next_command) printf("procedure %s has been called\n",str2);}
void animate(int *iptr,char str[],void (*funptr)(), char fstr[])
{
str2=fstr;
our_func=funptr;
Int1Save = getvect(1); // save old interrupt//
setvect(1,my_inter);
asm { pushf //TF is ON//
pop ax
or ax,100000000B
push ax
popf}}
void unanimate()
{asm { pushf //TF is OFF//
pop ax
and ax,1111111011111111B
push ax
popf}
setvect (1,Int1Save); //restore old interrupt//}
void main(void)
{int i;
int f1 = 1;
int f2 = 1;
int fibo = 1;
animate(&fibo, "fibo", sleep, "sleep");
for(i=0; i < 8; i++)
{
sleep(2);
f1 = f2;
f2 = fibo;
fibo = f1 + f2;} // for//
unanimate();} // main//
My question...
Off course the problem is at "my inter" on the inline assembly. but can't figure it out.
What am I doing wrong? (please take a look at the code above)
I wanted to save the address of the pointer for the specific procedure (sleep) in the volatile our_func. then take the info (address to each next command) from the stack to volatile next_command and then finaly returnning to c and make the compare each time. If the same value (address) is on both variables then to print a specific message.
Hope I'm clear..
10x,
Nir B
Answered as a comment by the OP
I got the answer I wanted:
asm { MOV SI,[BP+18] //Taking the address of each command//
MOV DI,[BP+20]
MOV word ptr next_command+2,DI
MOV word ptr next_command,SI}
if ((*our_func)==(*next_command)) //Making the next_command compare//
printf("procedure %s has been called\n",str2);

Multithreading with inline assembly and access to a c variable

I'm using inline assembly to construct a set of passwords, which I will use to brute force against a given hash. I used this website as a reference for the construction of the passwords.
This is working flawlessly in a singlethreaded environment. It produces an infinite amount of incrementing passwords.
As I have only basic knowledge of asm, I understand the idea. The gcc uses ATT, so I compile with -masm=intel
During the attempt to multithread the program, I realize that this approach might not work.
The following code uses 2 global C variables, and I assume that this might be the problem.
__asm__("pushad\n\t"
"mov edi, offset plaintext\n\t" <---- global variable
"mov ebx, offset charsetTable\n\t" <---- again
"L1: movzx eax, byte ptr [edi]\n\t"
" movzx eax, byte ptr [charsetTable+eax]\n\t"
" cmp al, 0\n\t"
" je L2\n\t"
" mov [edi],al\n\t"
" jmp L3\n\t"
"L2: xlat\n\t"
" mov [edi],al\n\t"
" inc edi\n\t"
" jmp L1\n\t"
"L3: popad\n\t");
It produces a non deterministic result in the plaintext variable.
How can i create a workaround, that every thread accesses his own plaintext variable? (If this is the problem...).
I tried modifying this code, to use extended assembly, but I failed every time. Probably due to the fact that all tutorials use ATT syntax.
I would really appreciate any help, as I'm stuck for several hours now :(
Edit: Running the program with 2 threads, and printing the content of plaintext right after the asm instruction, produces:
b
b
d
d
f
f
...
Edit2:
pthread_create(&thread[i], NULL, crack, (void *) &args[i]))
[...]
void *crack(void *arg) {
struct threadArgs *param = arg;
struct crypt_data crypt; // storage for reentrant version of crypt(3)
char *tmpHash = NULL;
size_t len = strlen(param->methodAndSalt);
size_t cipherlen = strlen(param->cipher);
crypt.initialized = 0;
for(int i = 0; i <= LIMIT; i++) {
// intel syntax
__asm__ ("pushad\n\t"
//mov edi, offset %0\n\t"
"mov edi, offset plaintext\n\t"
"mov ebx, offset charsetTable\n\t"
"L1: movzx eax, byte ptr [edi]\n\t"
" movzx eax, byte ptr [charsetTable+eax]\n\t"
" cmp al, 0\n\t"
" je L2\n\t"
" mov [edi],al\n\t"
" jmp L3\n\t"
"L2: xlat\n\t"
" mov [edi],al\n\t"
" inc edi\n\t"
" jmp L1\n\t"
"L3: popad\n\t");
tmpHash = crypt_r(plaintext, param->methodAndSalt, &crypt);
if(0 == memcmp(tmpHash+len, param->cipher, cipherlen)) {
printf("success: %s\n", plaintext);
break;
}
}
return 0;
}
Since you're already using pthreads, another option is making the variables that are modified by several threads into per-thread variables (threadspecific data). See pthread_getspecific OpenGroup manpage. The way this works is like:
In the main thread (before you create other threads), do:
static pthread_key_y tsd_key;
(void)pthread_key_create(&tsd_key); /* unlikely to fail; handle if you want */
and then within each thread, where you use the plaintext / charsetTable variables (or more such), do:
struct { char *plainText, char *charsetTable } *str =
pthread_getspecific(tsd_key);
if (str == NULL) {
str = malloc(2 * sizeof(char *));
str.plainText = malloc(size_of_plaintext);
str.charsetTable = malloc(size_of_charsetTable);
initialize(str.plainText); /* put the data for this thread in */
initialize(str.charsetTable); /* ditto */
pthread_setspecific(tsd_key, str);
}
char *plaintext = str.plainText;
char *charsetTable = str.charsetTable;
Or create / use several keys, one per such variable; in that case, you don't get the str container / double indirection / additional malloc.
Intel assembly syntax with gcc inline asm is, hm, not great; in particular, specifying input/output operands is not easy. I think to get that to use the pthread_getspecific mechanism, you'd change your code to do:
__asm__("pushad\n\t"
"push tsd_key\n\t" <---- threadspecific data key (arg to call)
"call pthread_getspecific\n\t" <---- gets "str" as per above
"add esp, 4\n\t" <---- get rid of the func argument
"mov edi, [eax]\n\t" <---- first ptr == "plainText"
"mov ebx, [eax + 4]\n\t" <---- 2nd ptr == "charsetTable"
...
That way, it becomes lock-free, at the expense of using more memory (one plaintext / charsetTable per thread), and the expense of an additional function call (to pthread_getspecific()). Also, if you do the above, make sure you free() each thread's specific data via pthread_atexit(), or else you'll leak.
If your function is fast to execute, then a lock is a much simpler solution because you don't need all the setup / cleanup overhead of threadspecific data; if the function is either slow or very frequently called, the lock would become a bottleneck though - in that case the memory / access overhead for TSD is justified. Your mileage may vary.
Protect this function with mutex outside of inline Assembly block.

Resources