I have a basic bootloader in c, but when I try to pass a parameter to a function, it doesn't work quite right.
The following code doesn't work:
__asm__(".code16\n");
__asm__("call main\n");
void main(){
putchar('X');
while(1){}
}
void putchar(char c){
__asm__("movb %0, %%al\n" : : "r"(c));
__asm__("movb $0x0e, %ah\n");
__asm__("int $0x10\n");
}
It should print out an X, but instead it just moves the cursor forward as if printing a space.
The following code works because it doesn't pass the character as a parameter:
__asm__(".code16\n");
__asm__("call main\n");
char c;
void main(){
c = 'X';
putchar();
while(1){}
}
void putchar(){
__asm__("movb %0, %%al\n" : : "r"(c));
__asm__("movb $0x0e, %ah\n");
__asm__("int $0x10\n");
}
Can someone explain why it isn't working?
The problem wasn't the fact that it was being passed as a parameter, but rather, I was using the assembly wrongly. The following code works:
__asm__(".code16\n");
__asm__("call main\n");
void main(){
putchar('!');
while(1){}
}
void putchar(char c){
__asm__ __volatile__("int $0x10" : : "a"(0x0e00 | c), "b"(0x0007));
}
Related
The code doesn't work in my Xcode compiler. It says *&point expected '('. I really don't know what goes wrong. It should have worked.
#include<stdio.h>
#include<stdlib.h>
void transformCopy(int *point);
void transformTrue(int *&point);
int main(){
int *a,*b,i=0;
transformTrue(a);
transformCopy(b);
for(i=0;i<5;i++) {a[i]=i;}
for(i=0;i<5;i++){printf("%d ",a[i]);}
printf("\n");
for(i=0;i<5;i++) {b[i]=i;}
for(i=0;i<5;i++){printf("%d ",b[i]);}
printf("\n");
return 0;
}
void transformCopy(int *point){
point=(int*)malloc(5*sizeof(int));
}
void transformTrue(int *&point){
point=(int*)malloc(5*sizeof(int));
}
*&point expected '('.
References do not exist in C ( void transformTrue(int *&point) ), this is C++ code, not C
If you want to have the equivalent in C you have to use void transformTrue(int **point) and you have to call transformTrue(&a);
If I change your code to do in C what it is done in C++ (see comments) :
#include<stdio.h>
#include<stdlib.h>
void transformCopy(int *point);
void transformTrue(int ** point); /* ** rather than *& */
int main(){
int *a,*b = 0,i=0;
transformTrue(&a); /* &a rather than just a */
transformCopy(b);
for(i=0;i<5;i++) {a[i]=i;}
for(i=0;i<5;i++){printf("%d ",a[i]);}
printf("\n");
for(i=0;i<5;i++) {b[i]=i;}
for(i=0;i<5;i++){printf("%d ",b[i]);}
printf("\n");
return 0;
}
void transformCopy(int *point){
point=(int*)malloc(5*sizeof(int));
}
void transformTrue(int ** point){ /* ** rather than *& */
*point=(int*)malloc(5*sizeof(int)); /* *point = rather than point = */
}
transformTrue(&a) modifies the value of a, but transformCopy(b); does nothing except locally (and a memory leak) and back in main the value of b is still 0, the program will crash when you will try to write in invalid addresses
one possibility is to change transformCopy like that :
int * transformCopy(){
return (int*)malloc(5*sizeof(int));
}
and of course the call to have b = transformCopy();
This question already has answers here:
In C, calling a function from main [closed]
(6 answers)
Closed 4 years ago.
#include<stdio.h>
void check_alphabets(char array_string[],int n){
char alphabet_array[n];
int i,j,val;
int alphabet_array_counter=0;
for(i=0;i<n;i++){
val=array_string[i];
if((val>=65 && val<=90) || (val>=97 && val<=122)){
alphabet_array[alphabet_array_counter]=array_string[i];
alphabet_array_counter++;
}
}
for(j=0;j<n;j++){
printf("%c",alphabet_array[j]);
}
}
void check_number(char array_string[],int n){
char number_array[n];
int i,j,val;
int number_array_counter=0;
for(i=0;i<n;i++){
val=array_string[i];
if(val>=30 && val<=39){
number_array[number_array_counter]=array_string[i];
number_array_counter++;
}
}
for(j=0;j<n;j++){
printf("%c",number_array[j]);
}
}
void check_character(char array_string[],int n){
char character_array[n];
int i,j,val;
int character_array_counter=0;
for(i=0;i<n;i++){
val=array_string[i];
if((val>=32 && val<=47) || (val>=58 && val<=64) || (val>=91 && val<=96) || (val>=123 && val<=127)){
character_array[character_array_counter]=array_string[i];
character_array_counter++;
}
}
for(j=0;j<n;j++){
printf("%c",character_array[j]);
}
}
void main(){
int size=100;
char array_string[size];
printf("Enter string? ");
scanf("%s",array_string);
int i=0,count=0;
while(array_string[i]!='\0'){
count++;
i++;
}
printf("size is %d",count);
void check_alphabets(array_string,count);
void check_number(array_string,count);
void check_character(array_string,count);
}
I have the above piece of code . I don't know what is wrong with it .No matter what I modify The functions are not getting executed.
I am compiling using gcc in ubuntu 18.
But whenever I try to compile it throws a warning which is
In function main
warning:parameter names(without types) in function declaration void check_alphabets(array_string,count)
this warning shows with all the calls from main.
I googled but couldn't find any solution.
These are not function calls:
void check_alphabets(array_string,count);
void check_number(array_string,count);
void check_character(array_string,count);
These are declarations. The return type in front of the function name tells us this is a declaration. When you call a function, you don't need to say what the return type is:
check_alphabets(array_string,count);
check_number(array_string,count);
check_character(array_string,count);
void check_alphabets(array_string,count);
void check_number(array_string,count);
void check_character(array_string,count);
these lines are not function calls. YOu mean
check_alphabets(array_string,count);
check_number(array_string,count);
check_character(array_string,count);
The warning you are getting is because the compiler thinks you are trying to declare a function, but your syntax is an invalid function declaration (argument names without types)
First, you have to learn how to use Markdown to format your code properly. Secondly, you're not calling your functions in main, you are only declaring them.
void check_alphabets(array_string,count);
void check_number(array_string,count);
void check_character(array_string,count);
must become
check_alphabets(array_string,count);
check_number(array_string,count);
check_character(array_string,count);
This code throws out an error saying that "code undelcared."
#include<stdio.h>
#define MAIN() c##o##d##e
int main()
{
MAIN();
printf("C program");
return 0;
}
int code()
{
printf("C is life");
}
Whereas, this code runs smoothly.
#include<stdio.h>
#define MAIN() m##a##i##n
int main()
{
MAIN();
printf("C program");
return 0;
}
int code()
{
printf("C is life");
}
Output:
C program
This code also runs smoothly.
#include <stdio.h>
#define macro(n, a, i, m) m##a##i##n
#define MAIN macro(n, a, i, m)
int MAIN()
{
printf("C is life");
return 0;
}
Output:
C is life
In the first code, why doesn't the code work as like main? I don't know what is the process after the concatenation 'main' is completed by the macro. Kindly explain the process behind these codes, in simple terms. Thanks in advance.
I also tried by defining the code function.
#include<stdio.h>
#define MAIN() c##o##d##e
int code(void);
int main()
{
MAIN();
printf("C program");
return 0;
}
int code(void)
{
printf("C is life\n");
return 0;
}
Output:
C program
So, defining a function should not be the problem. My question is, what happens after concatenation? Thanks in advance.
In C (since the C99 standard) you need to declare all functions before you use them.
In the first example you haven't declared the code function before you attempt to use it. You solve it by adding a function prototype:
// Declare the function, also known as a function prototype
void code(void);
int main(void)
{
// ...
}
// Define the function
void code(void)
{
// ...
}
The second example works because you use main which is already declared at that point. If a function haven't been declared before, the definition also declares the function.
Also note that your macro after expansion doesn't actually call the code (or the main) function. This is good, since calling main recursively (directly or indirectly) is generally bad.
In C, you have to define the prototype of your function int code () before any calls :
int code (void);
The function main is declared in assembly code, this is why your second version compiles et runs correctly.
If you want to avoid this error please add -Wmissing-prototypes compilation flag in order to let the compiler checks for you if your function has a prototype.
The problem is that code() function is not yet declared when main() is compiled.
Either move code() before main():
#include<stdio.h>
#define MAIN() c##o##d##e
int code()
{
printf("C is life");
}
int main()
{
MAIN();
printf("C program");
return 0;
}
Or forward declare code():
#include<stdio.h>
#define MAIN() c##o##d##e
int code();
int main()
{
MAIN();
printf("C program");
return 0;
}
int code()
{
printf("C is life");
}
Just remember macros are replaced at preprocessor stage itself. In C, every function needs to be prototyped before using/calling it so that compiler knows in advance about it's arguments and return type to avoid conflicts.
Case 1 :- when below code blocks executes, macro name MAIN() got replaced with code.
#define MAIN() c##o##d##e
int main(){
MAIN();
printf("C program");
return 0;
}
int code(){
printf("C is life");
}
And it looks like below after pre-processor stage
int main(){
code; /* errorenous statement */
printf("C program");
return 0;
}
int code(){
printf("C is life");
}
observe the line code; in above code block, it cause the compilation error. When you run above code like gcc -Wall -Wstrict-prototypes -Werror test.c where it will convert warning into error.
error: ‘code’ undeclared (first use in this function) #define MAIN()
c##o##d##e
^
to solve this, declare the code() like before #define
int code(void); /* declaration */
There is one more warning converted into error
error: statement with no effect [-Werror=unused-value] #define MAIN()
c##o##d##e
Because after macro replacement it looks like code; and here compiler rightly complaining above statement with no effect. So to avoid this
change the macro name from MAIN() to MAIN. for e.g
#define MAIN c##o##d##e
Correct version of case-1 code
#include<stdio.h>
int code(void);
#define MAIN c##o##d##e
int main(void){
MAIN();
printf("C program");
return 0;
}
int code(void){
printf("C is life");
return 0;
}
And it produces output as
C is lifeC program
Case 2 :- when below code executes, macro name MAIN() gets replaced with main
#define MAIN() m##a##i##n
int main(){
MAIN();
printf("C program");
return 0;
}
int code(){
printf("C is life");
}
And it looks like at preprocessor stage
int main(){
main; /* it causes error */
printf("C program");
return 0;
}
int code(){
printf("C is life");
}
Case 3 :- when below code blocks executes, macro name MAIN() got replaced with code & here you declared the code() also.
#define MAIN() c##o##d##e
int code(void);
int main() {
MAIN();
printf("C program");
return 0;
}
int code(void) {
printf("C is life\n");
return 0;
}
And it looks like below after pre-processor stage
int code(void);
int main() {
code;/* error causing statement */
printf("C program");
return 0;
}
int code(void) {
printf("C is life\n");
return 0;
}
Suggest you to compile any C code with
gcc -Wall -Wstrict-prototypes -Werror test.c
so by converting warning to error you will learn more.
I'm wondering something like this is possible:
// declaration
void func();
int main()
{
int ar[] = { 1, 2, 3 };
func(ar); // call with parameter
return 1;
}
void func() // no parameters
{
// do something
}
Can someone explain me this and especially how can I access ar in func()?
In C (not C++), a function declared as func() is treated as having an unspecified number of untyped parameters. A function with no parameters should be explicitly declared as func(void).
A hack would be to exploit the GCC calling convention.
For x86, parameters are pushed into stack. Local variables are also in the stack.
So
void func()
{
int local_var;
int *ar;
uintptr_t *ptr = &local_var;
ptr += sizeof(int *);
ar = (int *)ptr;
May give you the array address in ar in x86.
For x86_64, the first parameter is stored in rdi register.
void func()
{
uintptr_t *ptr;
int *ar;
asm (
"movq %%rdi, %0"
:"=r"(*ptr)
:
:"rdi");
ar = (int *)ptr;
May give you the array address in ar in x86_64.
I have not tested these code myself and you may be to fine tune the offsets yourself.
But I am just showing one possible hack.
If you want to use any function with no parameters with any return type, it should be declared as (In C)
return_type func(void). It is only generic way of function declaration.
But any how, for your question , it possible to access but not generic..Try this program...
#include<stdio.h>
int *p;
void func();
int main()
{
int ar[] = { 1, 2, 3 };
p=ar;
printf("In main %d\n",ar[0]);
func(ar); // call with parameter
printf("In main %d\n",ar[0]);
return 1;
}
void func() // no parameters
{
printf("In func %d \n",*p);
*p=20;
}
Even this program works fine, it is not generic way and also is undefined.
if you declare function like void func (void) ,it will not work.
You can't access ar in func(), since you dont have a reference to it in func().
It would be possible if ar would be a global var or you have a pointer on it.
So that you can do something with func(), you need to pass it the input data you'll work with.
First you must declare the function properly :
// declaration
void func(int []);
The define it :
void func( int a[] )
{
// do something
printf ("a[0] = %d\n", a[0]);
}
Full code :
#include <stdio.h>
// declaration
void func(int []);
int main()
{
int ar[] = { 1, 2, 3 };
func(ar); // call with parameter
return 1;
}
void func( int a[] )
{
// do something
printf ("a[0] = %d\n", a[0]);
}
This will display :
a[0] = 1
You can implement something like this.
void func(int *p, int n);
int main()
{
int ar[] = { 1, 2, 3 };
func(ar, sizeof (ar)/sizeof(ar[0]) ); // call with parameter
return 1;
}
void func(int *p, int n) // added 2 parameters
{
int i=0;
for (i=0; i<n; ++i){
printf ("%d ", p[i]);
}
}
I am trying to write an inline assebly function which exchanges two values.( and i'm using extended ASM format)
This code works:
#include <stdio.h>
void Exchange(int *x, int *y)
{
printf("In Exchange function: Before exchange x is: %d\n",*x);
printf("In Exchange function: Before exchange y is: %d\n",*y);
asm("xchg %%eax,%%edx\n\t" \
:"+a"(*x),"+d"(*y));
printf("In Exchange function: After exchange x is: %d\n",*x);
printf("In Exchange function: After exchange y is: %d\n",*y);
}
int main()
{
int x=20;
int y=30;
printf("In main: Before exchange x is: %d\n",x);
printf("In main: Before exchange y is: %d\n",y);
Exchange(&x,&y);
printf("In main: After exchange x is: %d\n",x);
printf("In main: After exchange y is: %d\n",y);
return 0;
}
but when i try to wirte it in full assembly like below i get segmentation fault (core dumped) error.
void Exchange(int *x, int *y)
{
asm("subl $8,%%esp\n\t" \
"movl %%eax,4(%%esp)\n\t" \
"movl %%edx,(%%esp)\n\t" \
"call printf\n\t" \
"addl $8,%%esp\n\t" \
"xchg %%eax,%%edx\n\t" \
"subl $8,%%esp\n\t" \
"movl %%eax,4(%%esp)\n\t" \
"movl %%edx,(%%esp)\n\t" \
"call printf\n\t" \
"addl $8,%%esp\n\t" \
:"+a"(*x),"+d"(*y));
}
int main()
{
int x=20;
int y=30;
printf("In main: Before exchange x is: %d\n",x);
printf("In main: Before exchange y is: %d\n",y);
Exchange(&x,&y);
printf("In main: After exchange x is: %d\n",x);
printf("In main: After exchange y is: %d\n",y);
return 0;
}
Aren't we allowed to use printf function in the assembly section?
Your asm code calls printf with two integer arguments -- no format string. So it tries to dereference the first integer as a pointer to a format string and crashes.
Also, calling printf will clobber the values in %eax and %edx, as they are not preserved across calls in the standard x86 calling conventions.