Article Directory
Zero. Foreword
Because I’m going to take the exam tomorrow, but my own 51 single-chip microcomputer is still at the level of C language development, but the exam requires assembly, so take a little time to learn "compiled automata" (in fact, I used the common keywords if
, for
, []
give inflicted compiled version, easy to write code).
Since I have been exposed to reverse engineering before, I have a bit of assembly foundation and proficient use of C language to program 51 single-chip microcomputers, so the focus of this article is on the C转汇编
above, and in order to cope with the exam, only choose 比较好记
the way, not pay attention to it. Code efficiency.
1. Structure
In assembly, since the code is executed in order of address, so for convenience, each I used a function, such as if
, for
gave 封装
as a function, such clear logic easy to remember.
I have a habit. The accumulator is not used for data storage, but only for calculations and temporary variables, not for storage; if it is stored, it is used to use the working register R n for storage.
2. Judgment statement
In C language, our if is like this:
if (condition)
{
}
else
{
}
And CJNE
is suitable for a relatively large range of instruction, so we based on it, write a judge sentences:
JUDGE: CJNE R0, #01H, JFALSE
MOV R1, #0FFH
RET
JFALSE: MOV R1, #00H
RET
This command is to determine whether R0 is 0x01
, if it 0xFF
is, then assign a value to R1 , if not, then assign a value 0
. Equivalent:
if (R0 == 0x01)
{
R1 = 0XFF;
return;
}
else
{
R1 = 0x00;
return;
}
For example, this is a program that judges the value of R0 and
lights up: the
light is on: the light is off:
Three. Loop statement
Our analysis of a C language, I wrote it in a more beautiful form:
R2 = 5;
while(--R2 > 0)
{
//express
}
This is a very basic cycle, then we can use DJNZ
to simulate this function:
REPEATINIT: MOV R2, #05H
REPEATBEGIN:DJNZ R2, REPEATEXPRE
RET
REPEATEXPRE:INC A
SJMP REPEATBEGIN
This code will be executed ++A
4 times because it is subtracted first.
Grab and replace the C language code as:
R2 = 5; // REPEATINIT
while(--R2 > 0) // REPEATBEGIN
{
++A; // REPEATEXPRE
}
return; // RET
This is a code that makes P2+4 every time:
Of course, there is also an infinite loop statement:
while(--R5);
This code can be replaced with the following code:
DJNZ R5, $
Four. Subscript []
In assembly, in fact, the address of a segment is a continuous method that can be used [基址]+偏移指针
to simulate an array, so in general, we use this method to look up the table: the
base address is replaced by DPTR, such as:
MOV DPTR,#TAB
This can be MOVC A,@A+DPTR (A=0、1、2……len)
used to assign the contents of TAB to A.
Example: 数组DB
The content in the loop assignment of P2 (the delay is not written, and the code effect
can be checked through the debugging step) is also lit like this:
●●●●●●●● FFH
○●●●●●●○ 7EH
○○ ●●●●○○ 7CH
○○○●●○○○ 18H
○○○○○○○○ 00H
But our cycle is to reduce from high to 0, so the index should be inverted.
Of course, you can use the number to subtract the value of the loop variable at this time to get the positive index.
Complete code:
ORG 0000H
MOV DPTR, #TAB
LJMP MAIN
ORG 0100H
MAIN: LCALL REPEATINIT
SJMP MAIN
REPEATINIT: MOV R0, #06
REPEATBEGIN:DJNZ R0, REPEATEXPRE
RET
REPEATEXPRE:MOV A, R0
DEC A
MOVC A, @A+DPTR
MOV P2, A
SJMP REPEATBEGIN
TAB: DB 00H,18H,3CH,7EH,0FFH
END
Effect:
Just look at the red dot, it takes time for the diode to turn on and off, so there is a delay in the display:
……
Five. The nesting of judgment statements
For the nesting of judgment statements, in addition to multiple if
superimpositions, there is another switch
limitation. This method is more limited. The values of these schemes need to be continuous. For example switch(i) i=0、1、2……
, because the code of the single-chip microcomputer is stored continuously, the function address can also be used. By [基址]+偏移指针
the way.
For example, modify the state of P2 by modifying R0:
ORG 0000H
MOV R0, #0
LJMP MAIN
ORG 0100H
MAIN: LCALL SwitchInit
SJMP MAIN
SwitchInit: MOV DPTR, #Switch
CLR A
MOV A, R0
MOV B, #3
MUL AB
ADD A, #1
Switch: JMP @A+DPTR
LJMP FUN0
LJMP FUN1
LJMP FUN2
FUN0: MOV P2, #0H
RET
FUN1: MOV P2, #0FH
RET
FUN2: MOV P2, #0F0H
RET
How to understand? First, we set the offset × 3 because LJMP occupies three machine codes:
so we only need the offset A × 3+1 to get the address where our jump statement is located.
This code is equivalent to:
void SwitchInit(int A)
{
switch(3*A+1)
{
case &FUN0: FUN0();
case &FUN1: FUN1();
case &FUN2: FUN2();
}
}
// SwitchInit并不会反回到CALL时入栈的地址,而是在FUN里通过RET,将PC指向入栈前地址(听不懂这句话也没关系)。
Six. Nesting of loop statements
For the one-fold loop just written
R2 = 5; // REPEATINIT
while(--R2 > 0) // REPEATBEGIN
{
++A; // REPEATEXPRE
}
return; // RET
We can give it a grade:
R1 = 5; // REINIT
while(--R1 > 0) // RE1BEG
{
R2 = 5; // express
while(--R2 > 0) // RE2BEG
{
// express
}
}
return; // RET
For example, write a running light:
ORG 0000H
LJMP MAIN
ORG 0100H
MAIN: MOV A, #01H
LOOP: MOV P2, A
RL A
LCALL REINIT
SJMP LOOP
REINIT: MOV R1,#20
RE1BEG: DJNZ R1,RE1EXP
RET ;RE1END
RE1EXP: MOV R2, #200
;More express
RE2BEG: DJNZ R2, RE2EXP
SJMP RE1BEG ;RE2END
RE2EXP: NOP
SJMP RE2BEG
Of course, if you don’t have RE2EXP, you can just jump in place:
REINIT: MOV R1,#20
RE1BEG: DJNZ R1,RE1EXP
RET ;RE1END
RE1EXP: MOV R2, #200
;More_express
RE2BEG: DJNZ R2, $
SJMP RE1BEG ;RE2END
Well, it looks very long-winded.
Seven. Some registers and overflow value algorithms to be memorized