内联汇编¶
内联汇编使用关键字__asm
。
1 2 3 | __asm{ //汇编指令 } |
内联汇编中仅支持汇编指令,不支持汇编控制语句,无法在汇编中定义变量。
汇编指令之间必须使用分号;
分割,仅仅换行是不行的。
注意
C语言定义的名字为a
/A
的元素在内联汇编中无法访问,因为其与累加器同名,应避免这种情况。
内联汇编访问data变量¶
data变量的名字在内联汇编中可以直接使用,其代表的即为变量的地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | char x = 12; uint16_t y; int32_t z; __asm{ //y = x mov A, x; mov y, A; and A, #0x80; sz A; mov A, #0xff; mov y + 1, A; //z = y + 5 mov A, y; add A, #5; mov z, A; mov A, #0; addc A, y + 1; mov z + 1, A; mov A, #0; addc A, y + 2; mov z + 2, A; mov A, #0; addc A, y + 3; mov z + 3, A; } |
内联汇编访问data数组¶
data数组的名字在内联汇编中可以直接使用,其代表的即为数组的首地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | uint8_t arr[10]; uint16_t sum = 0; __asm{ //循环为数组赋值 mov A, #arr; mov IADR, A; mov A, 0; loop_w: mov IDAT, A; inc IADR; inc A; se A, #10; jmp loop_w; //数组直接访问 mov A, #123; mov arr + 4, A; //数组求和 mov A, #arr; mov IADR, A; mov A, #10; mov A, IDAT; add sum, A; mov A, #0; addc sum + 1, A; inc IADR; dsz A; jmp $ - 6; } |
内联汇编访问code数组¶
由于code数组有两种存储方式,因此,访问时也要分两种。
单字节元素code数组¶
单字节元素code数组存储为跳转表形式,因此内联汇编中要以调用子程序的方式来访问,调用子程序前需将下标值放到累加器A
中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | //arr: __code uint8_t arr[10] = { //add PCL, A 0, //ret #0 1, //ret #1 2, //ret #2 3, //ret #3 4, //ret #4 5, //ret #5 6, //ret #6 7, //ret #7 8, //ret #8 9 //ret #9 }; uint8_t i = 0; uint16_t sum = 0; __asm{ //数组求和 mov A, i; call arr; add sum, A; mov A, #0; addc sum + 1, A; inc i; mov A, i; se A, #10; jmp $ - 8; } |
多字节元素code数组¶
多字节元素code数组直接以数据形式存储在code区,因此直接使用movc
指令即可访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | __code uint16_t arr[10] = { //arr: 0, //dw 0 1, //dw 1 2, //dw 2 3, //dw 3 4, //dw 4 5, //dw 5 6, //dw 6 7, //dw 7 8, //dw 8 9 //dw 9 }; uint8_t n = 10; uint16_t sum = 0; __asm{ //数组求和 mov A, #arr & 0xff; mov IAPADRL, A; mov A, #arr >> 8; mov IAPADRH, A; movc A; add sum, A; mov A, IAPDATH; addc sum + 1, A; isnz IAPADRL; inc IAPADRH; dsz n; jmp $ - 7; } |