Author Topic: Request. Assembly help. I have not got a clue how to do it.  (Read 10181 times)

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Like all things once you learn how to do things, it looks easy.  For the last 2 days I have been teaching myself basic assembly.  Bear in mind my knowledge of assembly is almost 0.  I will show you the code for the limit break bar in FF7, and explain why I cannot make it fill the needed amount of the graphic I created.   I need the bar to be 147 (93) pixels long at limit break time.

Limit Var.  Limit variable is the current state of a players limit bar.  It is 1 byte long (0-255).  00 is empty, FF is full (limit break).  The actual number sent to code below (at 006DD6A3 ) has 00 at the end (2 bytes).  So FF becomes FF00.


006DD6A1 - 33 C0                      - xor eax,eax
006DD6A3 - 66 8B 44 0A 1A             - mov ax,[edx+ecx+1A]
006DD6A8 - 99                         - cdq
006DD6A9 - 81 E2 FF030000             - and edx,000003FF
006DD6AF - 03 C2                      - add eax,edx
006DD6B1 - C1 F8 0A                  - sar eax,0A
006DD6B4 - 50                         - push eax

006DD6A1 - 33 C0                      - xor eax,eax 
Makes eax equal 0.

006DD6A3 - 66 8B 44 0A 1A             - mov ax,[edx+ecx+1A]
Retrieves the 3 characters limit vars at each loop from an address created by edx+ecx+1A.

006DD6A8 - 99                         - cdq
This seems to change a number into 64 bit?  But why is it here?  See the edit.

006DD6A9 - 81 E2 FF030000             - and edx,000003FF
EDX seems to be 0 by this point anyway? (well that might just because I can only see 32 bit addresses with this debugger)  I need this explaining too.

006DD6AF - 03 C2                      - add eax,edx
No idea what is going on here.

006DD6B1 - C1 F8 09                   - sar eax,0A

This is the crunch code.  It shifts the bits in eax 10 places to the right.  So if a character has FF00 at this point (limit break) it will first look like this:

1111111100000000 

which becomes :  00111111 (63).  The reason it does this is to correct the limitvar number for use for the BAR GRAPHIC, which is precisely what I am trying to edit.  So if a player has a limit break this is what happens>

FF00 becomes 3F, 3F is 63, so bar moves 63 pixels.  I assume that is correct.

006DD6B4 - 50                         - push eax

Reflects changes on the bar graphic.

But here is the key question.  How do I program this to make the bar 147 pixels at FF00?  Well, you cant without knowing what the f*ck you are doing.  And I don't.  In a nice high level language you would just multiply limitvar by a nice number like 0.4 to make it around 100 at limit break time.

So... can anyone explain this to me in laymans terms or rewrite the code above so that it will do this?

Thanks :)



edit:

in fact I can nop 006dd6a8 to 006dd6b0 without anything changing. [l spiro has explained this... it is all just a rounding operation]
« Last Edit: 2011-02-17 05:41:59 by DLPB »

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Quote
006DD6A8 - 99                         - cdq
This seems to change a number into 64 bit?  But why is it here, I can nop it and have no problem.
Unless the highest bit set in the 32-bit starting value is 1, EDX will be filled with 0’s and your end result will not be changed.  This represents most cases and thus you will mostly never see a change.


0xFF590CA0 after cdq =
Code: [Select]
EAX: 0xFF590CA0
EDX: 0xFFFFFFFF
Because EDX is filled based off the value of one bit, it will always either be all 0’s or all F’s.


Quote
006DD6A9 - 81 E2 FF030000             - and edx,000003FF
EDX seems to be 0 by this point anyway? (well that might just because I can only see 32 bit addresses with this debugger)  I need this explaining too.
And if it is not 0 (see above) it will be a regular AND.
Code: [Select]
EDX: 0xFFFFFFFF & 0x000003FF = 0x000003FF
By this point EDX will either be 0x00000000 or 0x000003FF.  Always.


Quote
006DD6AF - 03 C2                      - add eax,edx
No idea what is going on here.
Adding either 0x00000000 or 0x000003FF to EAX.
Code: [Select]
EAX: 0xFF590CA0 + 0x000003FF = 0xFF59109F

Quote
006DD6B1 - C1 F8 09                   - sar eax,0A

This is the crunch code.  It shifts the bits in eax 10 places to the right.  So if a character has FF00 at this point (limit break) it will first look like this:
Shifting down 10 bits as you say.
Notice however that 0x3FF is HB 00000011 11111111 LB (first 10 bits set).
Coincidence?

Code: [Select]
0xFF59109F >> 0xA = 0xFFFFD644 (Sign bit preserved). -10684

If they did not add EAX and EDX you would get this:
Code: [Select]
0xFF590CA0 >> 0xA = 0xFFFFD643 -10685


EDX becomes FFFFFFFF when the high bit in EAX is set.
The high bit in EAX is the sign bit.  If it is set, the number is negative.
Therefore EDX becomes FFFFFFFF when EAX is negative.

The code basically means that if EAX is negative, the result will be one value larger than just shifting off the bottom 10 bits unless all of the 10 lower bits of the original number are 0.

In other words, integer truncation towards 0.
Positive numbers (not divisible by 1,024) round down, and negative numbers round up.


Knowing that all the alien code is simply performing a rounding operation should help you to finish your task.


L. Spiro

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
I may have devised a better way than using floating point scaling, thanks l.Spiro :)  will get back to this soon.

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
yes I have sorted it without using floating point, here is what I did

xor eax,eax
mov ax,[edx+ecx+1A]
sar eax,08
mov 93, bx
mul bx
sar eax, 08
006DD6B4 - 50                         - push eax

xor eax,eax

Makes eax 0.

mov ax,[edx+ecx+1A]

Retrieves limitvar and places in ax.

sar eax,08

moves eax 8 bits to right to get limitvar to 1 byte again at ax.

mov 93, bx

Places 93 in bx

mul bx

multiplies bx (93) with ax (current limitvar)

sar eax, 08

right shifts 8 bits to complete the sum.

006DD6B4 - 50                         - push eax

reflects changes.

==========

If anyone has an easier way, please show me.  I tried imul, eax, eax, 93, but it creates an unsigned value.

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Try this:

Code: [Select]
006DD6A1 - 33 C0          - xor eax,eax
006DD6A3 - 8A 44 0A 1B    - mov al,[edx+ecx+1B] (you'll only move one byte; might be + 1A, but try the + 1B first)
006DD6A7 - 6B C8 93       - imul 93
006DD6AA - C1 F8 08       - sar eax, 08 (not sure what you're going for here, care to explain?)
006DD6AD - 50             - push eax

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Thanks!

006DD6A7 - 6B C8 93       - imul 93

<  how does it know which register to multiply?

-----------

Edit.  That code doesn't work, (although changing to 1B was a very good idea cause it sorted the 1 byte issue faster).  imul 93 does not exist...

and the problem with using imul is that it tends to create signed numbers, so far I don't understand how to correct that, which is why I used mul

« Last Edit: 2011-02-17 18:38:19 by DLPB »

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Use shr instead of sar.  Shift right without carrying the sign bit.
Be sure to shift only AX, not EAX.

Also you are working primarily with AX but returning EAX at the end.  There may be trash in the upper bits of EAX.  Be sure to clear it.


L. Spiro

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
yup tried that...  not the same issue as before but none the less still comes out wrong.


DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Ok, mul does not like to be passed values unless it is from register or memory address so:

xor eax,eax
mov ax,[edx+ecx+1B]
Mul [00400380]
sar eax, 08
006DD6B4 - 50                         - push eax

works.  00400380 is a spare space in memory and the exe.  And since I am using 93 in 4 different places, it makes sense just to store this number on its own.

Mul will just take 93, multiply it by ax and store in ax.  I dunno why mul works like this, automatically multiplying by ax, whilst imul wants to be fed registers and so forth for knowing where to store.

Perhaps mul ax [address] is better syntax, and I can use mul bx etc?
« Last Edit: 2011-02-17 20:28:01 by DLPB »

Kudistos Megistos

  • Banned
  • *
  • Posts: 3929
    • View Profile
Seifer, is your "modify" button broken?

You've needlessly double posted twice in this thread and you should know better.

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #10 on: 2011-02-17 20:32:05 »
Ok, mul does not like to be passed values unless it is from register or memory address so:

xor eax,eax
mov ax,[edx+ecx+1B]
Mul [00400380]
sar eax, 08
006DD6B4 - 50                         - push eax

Don’t mix signs.
If you perform an unsigned multiplication, perform an unsigned shift (shr).


L. Spiro

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #11 on: 2011-02-17 21:42:37 »
Don’t mix signs.
If you perform an unsigned multiplication, perform an unsigned shift (shr).

I didn't know there was a signed shift. I wasn't paying that much attention I guess.


006DD6A7 - 6B C8 93  translates into "imul ax, 93h". My disassembler didn't specify that.

Quote
xor eax,eax
mov ax,[edx+ecx+1B]
Mul [00400380]
sar eax, 08
006DD6B4 - 50

NO! That's a word move! It needs to be mov al,[edx+ecx+1B]. Otherwise you're getting 1B and 1C as a word which happens to be 00FFh, but it's bad practice to do that.

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #12 on: 2011-02-17 22:08:18 »
edit: 


is al just a lower 8 bits of eax?

Ah it seems it is... I understand this now... pretty simple idea.

Thanks a lot :) Also, any idea how I would go about that code 2 different ways?

1.  using imul but keeping the sum working (I get leading FF prob cause its multiplying them signed)

2. Using floating point values to scale limitvar

oh and 3.

Why does mul[address] take 4 bytes from the address when the lower register ax, that it uses, is only 16 bit?  If it is storing the result in ax (16 bit), then what is the point of it trying to multiply 32 bit values?
« Last Edit: 2011-02-17 22:58:37 by DLPB »

obesebear

  • *
  • Posts: 1389
    • View Profile
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #13 on: 2011-02-18 04:18:01 »
Agreed about the double posting.  Easy does it there cowboy.

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #14 on: 2011-02-18 04:19:52 »
 8)  I forgot I could remove the post tbh until afterwards and it was a mistake.  :evil:  :-P

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #15 on: 2011-02-18 04:53:19 »
Why does mul[address] take 4 bytes from the address when the lower register ax, that it uses, is only 16 bit?  If it is storing the result in ax (16 bit), then what is the point of it trying to multiply 32 bit values?
Because the data stored at the given address is 4 bytes in size.


L. Spiro

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #16 on: 2011-02-18 05:04:56 »
But the address I gave it just has a 1 byte value.... in spare part of the exe.?

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #17 on: 2011-02-19 06:11:19 »
Are you sure it is reading 4 bytes?
It reads the number of bytes that matches the size of your register.
Make it 2 bytes.

http://www.drpaulcarter.com/pcasm/pcasm-book-pdf.zip


L. Spiro

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #18 on: 2011-02-19 06:18:14 »
It is definitely reading 4 bytes.  If I place in

93 00 00 00 it is fine.  If I place 93 00 00 FF it has an issue....  Perhaps it is matching eax and not ax?  I dunno really :P
« Last Edit: 2011-02-19 06:20:09 by DLPB »

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #19 on: 2011-02-19 12:57:26 »
I didn’t pay close attention to your original code.
Looking back I noticed you did not specify the register/size of the MUL and it defaults to 32 bits on x86.
If you want it to operate on AX then use MULW and 93 00.

This may not be recognized by all disassemblers (I assume that is what you are using).
Either load the 16-bit value into a register and operate on that or use 32-bit values to keep things simple.


L. Spiro
« Last Edit: 2011-02-19 13:01:06 by L. Spiro »

DLPB_

  • Banned
  • *
  • Posts: 11006
    • View Profile
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #20 on: 2011-02-19 20:11:36 »
Thanks :)  I'll try it! 8)

syntax error

  • *
  • Posts: 147
    • View Profile
Re: Request. Assembly help. I have not got a clue how to do it.
« Reply #21 on: 2011-02-20 17:00:05 »
I dasm'ed FF VII at first with Ursoft WinDASM and later with REC.

REC gives you a mix of asm and C as output and doesnt crash like my
best tool which dislikes big binaries.