SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help > Tutorials

Reply
 
Thread Tools Display Modes
Old 25/06/2016, 06:59 AM   #11
Yashas
Gangsta
 
Join Date: Jun 2012
Location: India
Posts: 867
Reputation: 295
Default Re: AMX Assembly (#emit)

Quote:
Originally Posted by Dutheil View Post
It is not exact. *(data + frm) stores the previous frame pointer and not the frame pointer.
Except if there is a difference between "frame" and "frame pointer".
Yes, the way I have written is quite ambiguous and the context is so wrong too. I was talking about the stack printed from the func() and I should have cleary mentioned that it is the FRM of the main. My intention was to convey that 0 is the FRM pointer's start. I mean, everything above and below is with respect to the frame but yeah, I agree with you that is misleading.

Thanks for letting me know.

Corrected it & added new information about FRAMEs.

Quote:
Originally Posted by Nero_3D View Post
You can't store pointers, you store addresses (absolute or relative)

And in that case the 0 is a relative address, relative to the current frame which is (DAT + FRM), so its the same
And nearly all addresses are relative to DAT
You are right but he was talking about something else. I said "frame" without mentioning of which function it was (caller or called function).

I was looking for suggestions to improve the tutorial. Let me know if you have any. I hope to make it unambiguous and complete by the end of this year. The ambiguity can be found only by a reader who is new to emit because most of us tend to implicitly assume the correct meanings of the ambiguous terms.

If you think there is any part which isn't covered in this tutorial, let me know that as well!

Changes to the tutorial:

Code:
The frame pointer ("FRM") points to the address at the bottom of the running function's header (can be treated as the address to the start of the stack for the running function). The stack pointer("STK") points to the last data put on to the stack.
Code:
The frame pointer ("FRM") points to the address at the bottom of the running function's header (can be treated as the address to the start of the stack for the running function). If that scared you, here is a much nicer way to say the same. The FRM pointer basically stores an address which points to the start of the stack. When you use an offset of a local variable (or that of an item on stack) , you add that offset to the FRM to get the address which is then added to DAT to get the absolute address. If you did not understand, no need to worry because you will get another chance at "Making function calls" section. The stack pointer("STK") points to the last data put on to the stack.
--------------------------------------------------------------------------------------------------

Code:
new x;
func(a,b)
{
	new z = 101;
	new y = 102;
	
	#emit POP.pri
	#emit STOR.pri x
		
	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);

        #emit POP.pri
	#emit STOR.pri x

	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

    printf("%d",x);

	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);

	#emit POP.pri
	#emit STOR.pri x

	//Nothing more to POP

	for(;;) { } //If I allow the function to return, it will crash the server (run-time error) because the POP instructions change the STK Register and the return instruction expects STK to be having the correct address so that the next POP instruction would pop the return address. Did not get it? More about this later.

    return x; //If this were to be executed, you would get a "Invalid memory access" run-time error.
}
main()
{
   new zyx = 1;
   func(1001,1002);
   new abc = 2;
}
Code:
102 ; y
101 ; x
16468 ; Function Frame
596 ; Return Address
8 ; Since we pushed 2 arguments, we had pushed 8
1001 ; argument 1
1002 ; argument 2
1 ; xyz, Local Variable from the previous function
Code:
new x;
func(a,b)
{
	new z = 101;
	new y = 102;
	
	#emit POP.pri
	#emit STOR.pri x
		
	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);

        #emit POP.pri
	#emit STOR.pri x

	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);
		
	#emit POP.pri
	#emit STOR.pri x

        printf("%d",x);

	#emit POP.pri
	#emit STOR.pri x

	printf("%d",x);

	#emit POP.pri
	#emit STOR.pri x

	//Nothing more to POP but lets investigate what is in the FRM register
        #emit LCTRL 5
	#emit STOR.S.pri z

	printf("FRM in func: %d", z);

	for(;;) { } //If I allow the function to return, it will crash the server (run-time error) because the POP instructions change the STK Register and the return instruction expects STK to be having the correct address so that the next POP instruction would pop the return address. Did not get it? More about this later.

    return x; //If this were to be executed, you would get a "Invalid memory access" run-time error.
}
main()
{
    new zyx ;
    #emit LCTRL 5
    #emit STOR.S.pri zyx

    printf("FRM in main: %d", zyx);

    zyx = 1;
    func(1001,1002);
    new abc = 2;
}
Code:
FRM in main: 17988
102 ; y
101 ; x
17988 ; Frame of "main"
1900 ; Return address
8 ; we pushed 2 arguments, number of bytes they take is 8
1001 ; argument 1
1002 ; argument 2
1 ; zyx local variable from the main()
FRM in func: 17960
--------------------------------------------------------------------------------------------------
Added

Code:
Before getting into the details, let us first discuss what that "frame" thing really means. As said in an earlier section, every item in the stack has a relative address with respect to frame pointer (the negative relative addresses we talked about). To obtain the complete address we add the relative address/offset to the frame pointer.

Just a note, I said 'complete address' actually it isn't, you need to add DAT to that address to obtain the actual address. Never mind if you don't understand it. The assembly OpCodes accept addresses relative to DAT everywhere so it shouldn't bother you. You will learn eventually as time passes.

Also note that abc is not yet on the stack when func is called nor is x there since x is a global variable and resides in the heap.
--------------------------------------------------------------------------------------------------

Last edited by Yashas; 25/06/2016 at 04:58 PM.
Yashas is offline   Reply With Quote
Old 15/07/2016, 03:00 PM   #12
Yashas
Gangsta
 
Join Date: Jun 2012
Location: India
Posts: 867
Reputation: 295
Default Re: AMX Assembly (#emit)

Updated all sections with new content.
More detailed explainations for parts which people found hard to understand (Reported via PM).
Fixed all ambigious explainations which were reported via PMs.

If you have suggestions/improvements, please let me know via PM. Also let me know if you find any part of the tutorial hard to understand so that it can be improved.
Yashas is offline   Reply With Quote
Old 05/08/2016, 07:07 PM   #13
Luicy.
Banned
 
Join Date: Dec 2014
Location: Sweden, Skövde
Posts: 831
Reputation: 79
Default Re: AMX Assembly (#emit)

This is wonderful, if I sometime get interested in AMX Assemblies, I will read this for sure.
Enjoy your reputation and keep it up.
Luicy. is offline   Reply With Quote
Old 26/08/2016, 09:16 PM   #14
Sanya4
Little Clucker
 
Join Date: Jun 2015
Posts: 38
Reputation: 4
Default Re: AMX Assembly (#emit)

WTF?! Just wanted to ask: Y_Less did it on purpose?!!111

IN "Usage of stack as temporary storage":
we see:
PHP Code:
     #emit POP.pri  //Pop the last pushed value into PRI 
     //last pushed was local, which had a value of 10 when pushed and hence PRI = 10

//by me: PRI is 10, ALT is 5

     #emit CONST.alt 5  //ALT = 5
     #emit SDIV //PRI = ALT / PRI (signed divide),ALT = ALT mod PRI

//by me: let's count, 5/10=0
// 5 mod 10= 5

    //Now ALT = 0 since 5 divides 10 completely and leaves no remainder
    //PRI = 2 since 10 divided by 5 gives 2 <=== WTF?! 
Did anyone get it? xD (Usually, in asm's it collects to PRI(As PRI is A, ALT is B, where a is accumulator register, b is base register))

IN "Finding the address of functions"

PHP Code:
new addr;
#emit CONST.pri func1
#emit STOR.S.pri addr 
Doesn't work with public function, should it be or what?!(Compared with funcidx)

IN "Accessing elements of arrays that are arguments"

PHP Code:
public OnPlayerCommandText(playerid,cmdtext[])
{
     new 
index 2;

     
#emit LOAD.S.alt cmdtext 
     #emit LOAD.pri index  //<==================== GOOD joke! 
#emit LOAD.pri index FACEPALM x999


Also it's ok:
PHP Code:
#emit LOAD.S.alt cmdtext 
You are loading a value, NOT address!
I think, it should be:
PHP Code:
#emit CONST.pri cmdtext 
And btw, write right sematics for IDXADDR:
PHP Code:
PRI ALT + (PRI × cell size) (calculate indexed address
Everyone can get it.
Change it to understandable(not everyone can understand it):
PHP Code:
 PRI ALT CELLSIZE PRI 
And where is wrong(who didn't get it):

PHP Code:
public OnPlayerCommandText(playerid,cmdtext[])
{
     new 
index 2;

     
#emit CONST.alt cmdtext 
     #emit LOAD.S.pri index 
     #emit IDXADDR //PRI = ALT + (PRI * cell size) (calculate indexed address)

    //Now PRI contains the address of the element stored in index 2 of cmdtext (cmdtext[2])

     #emit LOAD.I //PRI = [PRI] //Since PRI contains the address of cmdtext[2], [PRI] will give the value stored at index 2
     //Instead of using IDXADDR and then LOAD.I, you can do the same with just one instruction using LIDX
     //LIDX = PRI = [ALT + (PRI x cell size)]

I read until it, Gonna post more <s>bugs</s> easter eggs(maybe).
I see no the first time when Y_Less using trololo functions.

edit 1:

PHP Code:
main()
{
     new 
a[] = "AMX Assembly";
     new 
character;     
     
#emit ADDR.pri a
     #emit ADD.C 8
     #emit LOAD.I
     #emit STOR.S.pri character

     
printf("%c"character);

Just gonna wrote here. 8 is 2 symbols as cell is 4. u wouldn't understand maybe cos I wrote it.
PHP Code:
#emit ADD.C 4*n //where n is amount of symbols 
Sanya4 is offline   Reply With Quote
Old 27/08/2016, 03:14 AM   #15
Nero_3D
High-roller
 
Nero_3D's Avatar
 
Join Date: Jun 2007
Location: Germany
Posts: 3,757
Reputation: 646
Default Re: AMX Assembly (#emit)

Quote:
Originally Posted by Sanya4 View Post
IN "Usage of stack as temporary storage":
we see:
PHP Code:
//CODE 
Did anyone get it? xD (Usually, in asm's it collects to PRI(As PRI is A, ALT is B, where a is accumulator register, b is base register))
it should be PRI / ALT, ALT / PRI would be SDIV.alt
Quote:
Originally Posted by Sanya4 View Post
IN "Finding the address of functions"

PHP Code:
new addr;
#emit CONST.pri func1
#emit STOR.S.pri addr 
Doesn't work with public function, should it be or what?!(Compared with funcidx)
As far as I know it works flawless if the function is defined before this code
Quote:
Originally Posted by Sanya4 View Post
I think, it should be:
PHP Code:
#emit CONST.pri cmdtext 
#emit LOAD.S.alt cmdtext is correct, use const.pri to get the relative address (cmdtext would be 16)
__________________
Nero_3D is offline   Reply With Quote
Old 27/08/2016, 07:12 PM   #16
Sanya4
Little Clucker
 
Join Date: Jun 2015
Posts: 38
Reputation: 4
Default Re: AMX Assembly (#emit)

btw, can u give me link to all opcodes?(not found as well)

About getting address of function: I think funcidx returns id only for public(and count only publics)/

And why we are using LOAD.S.alt(it stores content, not address)? But CONST.pri loads addreess?!?!!?!?

edit 1:
semantic for sub:
WRONG:
PHP Code:
PRI ALT PRI 
right:
PHP Code:
PRI PRI -ALT 
semantic for sdiv:
WRONG:
PHP Code:
shown in example 
right:
PHP Code:
PRI PRI/ALT (quotient)
ALT PRI%ALT (the second register consists remainder
Sanya4 is offline   Reply With Quote
Old 27/08/2016, 10:15 PM   #17
Nero_3D
High-roller
 
Nero_3D's Avatar
 
Join Date: Jun 2007
Location: Germany
Posts: 3,757
Reputation: 646
Default Re: AMX Assembly (#emit)

Quote:
Originally Posted by Sanya4 View Post
btw, can u give me link to all opcodes?(not found as well)
Look into the Pawn Implementer's Guide

http://y-less.com/uploads/pawn-imp-3.0.3367.pdf (2005 version)
(Or in the rar file from the first post - 2007 version)

and search for Instruction reference (should be either page 94ff or 99ff)

Quote:
Originally Posted by Sanya4 View Post
About getting address of function: I think funcidx returns id only for public(and count only publics)
funcidx returns the index in the public table, see the implementer's guide

Quote:
Originally Posted by Sanya4 View Post
And why we are using LOAD.S.alt(it stores content, not address)? But CONST.pri loads addreess?!?!!?!?
you needs to use load.s.alt because arrays are always passed by reference (only the address is passed)
const.pri/alt doesn't load anything, it just puts the given value into pri/alt

Doing load.s.alt cmdtext would load the address where content of cmdtext is saved
however doing const.alt cmdtext would only transfer the relative address into alt

const.pri/alt 5 // pri/alt = 5
const.pri/alt global_variable // gets address relative to DAT section
const.pri/alt local_variable // gets address relative to FRAME
const.pri/alt function // gets address relative to COD

also add.c cmdtext is the same as add.c 16
__________________
Nero_3D is offline   Reply With Quote
Old 28/08/2016, 07:35 AM   #18
JakeXxX
Big Clucker
 
JakeXxX's Avatar
 
Join Date: Sep 2015
Location: Inside
Posts: 197
Reputation: 29
Default Re: AMX Assembly (#emit)

Nice tutorial!
JakeXxX is offline   Reply With Quote
Old 31/01/2017, 10:14 PM   #19
spookie
Little Clucker
 
Join Date: Apr 2005
Posts: 8
Reputation: 18
Thumbs up Re: AMX Assembly (#emit)

Apologies for bumping an old thread, but this tutorial is fantastic!.. Fair play to you, Yashas!
spookie is offline   Reply With Quote
Old 01/02/2017, 12:03 PM   #20
HydraHumza
Gangsta
 
HydraHumza's Avatar
 
Join Date: Oct 2014
Posts: 651
Reputation: 130
Default Re: AMX Assembly (#emit)

A pretty decent tutorial. Really appreciate it.
__________________
Quote:
Originally Posted by Kalcor View Post
The fact is, I am right. And if you think I'm wrong, you are wrong.
HydraHumza is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Assembly Code CoaPsyFactor Scripting Help 2 18/08/2014 05:37 PM
Emit Assembly saamp Scripting Help 1 05/10/2013 09:04 PM
View compiler assembly output ReneG Scripting Help 2 08/05/2013 07:06 PM
Is this correct? (Assembly) The King's Bastard Scripting Help 0 31/01/2012 09:06 PM


All times are GMT. The time now is 08:17 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.