组装TASM大模型程序(从C调用)矩阵循环
Assembly TASM large model procedure (called from C) matrix loop
在程序集 8086 中编写了一个程序,它将从 C 接收以下内容:
int *matrix[size], int size, int *num1, int *num2.
我最初将其作为小模型编写,效果很好,当我将其转换为大模型时它停止正常工作,我尝试更改循环计数,"rows pointer" 加 4,"columns pointer" 加 2(尝试加 4 和相反)。
程序应该检查最小值(绝对值),即最小的 |x-y|。
例如,该过程将得到 N 个数,从所有其他数中减去它并始终保存 |x-y| 的最小值。之后它将N个数字向前移动一个数字,并与其余数字进行相同的检查,直到所有矩阵都被检查。
C代码(这个不能改):
#include <stdio.h>
#include <stdlib.h>
extern int getDiffMin(int *mat[], int size , int *num1 , int *num2);
int main()
{
int
diff , i, j , num1 , num2;
int **mat = (int **)malloc(sizeof(int *) * 4);
for (i = 0; i < 4; i++)
mat[i] = (int *)malloc(sizeof(int) * 4);
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
mat[i][j] = (i*j) - (5 * i) - (14 * j);
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
printf("%d\t", mat[i][j]);
printf("\n");
}
diff = getDiffMin(mat, 4 , &num1 , &num2);
printf("\nminDiff == |(%d)-(%d)| = %d", num1 , num2 , diff);
for (i = 0; i < 4; i++)
free(mat[i]);
free(mat);
return 0;
}
汇编代码:
;extern int getDiffMin(int *mat[], int size , int *num1 , int *num2)
; BP+6+8 BP+10 BP+12+14 BP+16+18
;
.MODEL LARGE ;Pointers size = 4 bytes
.DATA
I DW ?
J DW ?
N DW ?
Min DW ?
TempI DW ?
TempJ DW ?
Counter DW ?
Two DW 2
.CODE
.386
PUBLIC _getDiffMin
_getDiffMin PROC FAR
Start:
PUSH BP ;Save BP's current value
MOV BP,SP
PUSH SI
PUSH DI
PUSH CX
PUSH ES
PUSH GS
MOV CX,WORD PTR [BP+10] ;CX point to size (matrix of size*size)
MOV SI,WORD PTR [BP+6] ;SI point to pointer in *mat[] (points to rows)
MOV ES,WORD PTR [BP+8] ;Segment of *mat[]
MOV DI,WORD PTR ES:[SI] ;DI point to value in *mat[] (points to columns, with first pointer on rows so gives value)
MOV ES,WORD PTR ES:[SI+2] ;Segment of *mat[]
MOV I,0 ;Rows index counter
MOV J,0 ;Columns index counter
MOV Counter,CX
ADD Counter,CX ;Counter for loop
FirstGetN: ;Get number to check with all other numbers
MOV AX,WORD PTR ES:[DI] ;AX has value which DI is pointing to
MOV N,AX
FirstSubNumbers:
ADD DI,2 ;Point to next column
MOV AX,WORD PTR ES:[DI] ;AX has value one column ahead from N
SUB AX,N
CMP AX,0
JG Continue1
NEG AX ;Convert sub result to positive
Continue1:
MOV Min,AX ;Save minimum difference in Min for loop with compare ahead
MOV SI,WORD PTR [BP+12] ;SI point to *num1 (in case first check had the minimum difference)
MOV GS,WORD PTR [BP+14] ;Segment of *num1
MOV AX,N
MOV GS:[SI],AX ;*num1 = N
MOV SI,WORD PTR [BP+16] ;SI point to *num2
MOV GS,WORD PTR [BP+18] ;Segment of *num2
MOV AX,WORD PTR ES:[DI] ;AX = second number
MOV GS:[SI],AX ;*num2 = second number
GetN:
MOV SI,WORD PTR [BP+6]
MOV ES,WORD PTR [BP+8]
ADD SI,I ;Add needed row
MOV DI,WORD PTR ES:[SI]
MOV ES,WORD PTR ES:[SI+2]
ADD DI,J ;Add needed column
MOV AX,WORD PTR ES:[DI]
MOV N,AX ;N contains number being checked with others
MOV AX,I ;In order to move from N location forward (numbers before were checked during the loop)
MOV TempI,AX
MOV AX,J
MOV TempJ,AX
MOV AX,Counter
CMP TempJ,AX ;Meaning it's in last column
JE Fix
AddJ:
ADD TempJ,2 ;Move to next column
JMP SubNumbers
Fix:
MOV TempJ,0 ;Back to first column
ADD TempI,4 ;New row
SubNumbers:
MOV SI,WORD PTR [BP+6]
MOV ES,WORD PTR [BP+8]
ADD SI,TempI
MOV DI,WORD PTR ES:[SI]
MOV ES,WORD PTR ES:[SI+2]
ADD DI,TempJ
MOV AX,WORD PTR ES:[DI] ;AX contains number to check with N
MOV BX,N ;Move N to BX in order to save N's value
SUB BX,AX ;BX (N) -= AX
CMP BX,0
JG Continue2
Neg BX
Continue2:
MOV AX,Min
SUB AX,BX ;Substract former minimum and current sub result
CMP AX,0 ;To check which one is bigger
JLE Continue3 ;If BX > AX
MOV Min,BX ;Else, Min=BX
MOV SI,WORD PTR [BP+12] ;SI point to *num1
MOV GS,WORD PTR [BP+14] ;Segment of *num1
MOV AX,N
MOV GS:[SI],AX ;*num1 = N
MOV SI,WORD PTR [BP+16] ;SI point to *num2
MOV GS,WORD PTR [BP+18] ;Segment of *num2
MOV AX,WORD PTR ES:[DI] ;AX = second number
MOV GS:[SI],AX ;*num2 = second number
Continue3:
MOV AX,Counter
CMP TempJ,AX ;Meaning all columns were checked
JNE AddJ
MOV TempJ,0 ;Else, go to first column
ADD TempI,4 ;Next row
MUL Two
CMP TempI,AX ;Meaning all rows (and columns) were checked
JNE SubNumbers
MOV AX,Counter
ADD J,2 ;Move to next column with N number (J is pointing to INT so advance 2 bytes)
CMP J,AX
JNE GetN
Fix2:
MOV J,0
MOV AX,Counter
MUL Two
ADD I,4
CMP I,AX ;If all rows have been checked with N number (I is pointing to pointer so jumps of 4 byte, LARGE MODEL)
JE Finish
JMP GetN
Finish:
MOV AX,Min ;Save value to return
POP GS ;POP by LIFO order
POP ES
POP CX
POP DI
POP SI
POP BP
RET ;AX, IP and CS
_getDiffMin ENDP
END Start
谢谢。
答案是我需要为 "loops" 添加 2,因为 'size'(来自 C 代码)从 0 开始计数。
这是 ASM 代码:
;extern int getDiffMin(int *mat[], int size , int *num1 , int *num2)
; BP+6+8 BP+10 BP+12+14 BP+16+18
;
.MODEL LARGE ;Pointers size = 4 bytes
.DATA
I DW ?
J DW ?
N DW ?
Min DW ?
TempI DW ?
TempJ DW ?
Counter DW ?
Two DW 2
.CODE
.386
PUBLIC _getDiffMin
_getDiffMin PROC FAR
Start:
PUSH BP ;Save BP's current value
MOV BP,SP
PUSH SI
PUSH DI
PUSH CX
PUSH ES
PUSH GS
MOV CX,WORD PTR [BP+10] ;CX point to size (matrix of size*size)
MOV SI,WORD PTR [BP+6] ;SI point to pointer in *mat[] (points to rows)
MOV ES,WORD PTR [BP+8] ;Segment of *mat[]
MOV DI,WORD PTR ES:[SI] ;DI point to value in *mat[] (points to columns, with first pointer on rows so gives value)
MOV ES,WORD PTR ES:[SI+2] ;Segment of *mat[]
MOV I,0 ;Rows index counter
MOV J,0 ;Columns index counter
MOV Counter,CX
ADD Counter,2 ;Since size starts from 0, need to make our "loop" bigger by 2
FirstGetN: ;Get number to check with all other numbers
MOV AX,WORD PTR ES:[DI] ;AX has value which DI is pointing to
MOV N,AX
FirstSubNumbers:
ADD DI,2 ;Point to next column
MOV AX,WORD PTR ES:[DI] ;AX has value one column ahead from N
SUB AX,N
CMP AX,0
JG Continue1
NEG AX ;Convert sub result to positive
Continue1:
MOV Min,AX ;Save minimum difference in Min for loop with compare ahead
MOV SI,WORD PTR [BP+12] ;SI point to *num1 (in case first check had the minimum difference)
MOV GS,WORD PTR [BP+14] ;Segment of *num1
MOV AX,N
MOV GS:[SI],AX ;*num1 = N
MOV SI,WORD PTR [BP+16] ;SI point to *num2
MOV GS,WORD PTR [BP+18] ;Segment of *num2
MOV AX,WORD PTR ES:[DI] ;AX = second number
MOV GS:[SI],AX ;*num2 = second number
GetN:
MOV SI,WORD PTR [BP+6]
MOV ES,WORD PTR [BP+8]
ADD SI,I ;Add needed row
MOV DI,WORD PTR ES:[SI]
MOV ES,WORD PTR ES:[SI+2]
ADD DI,J ;Add needed column
MOV AX,WORD PTR ES:[DI]
MOV N,AX ;N contains number being checked with others
MOV AX,I ;In order to move from N location forward (numbers before were checked during the loop)
MOV TempI,AX
MOV AX,J
MOV TempJ,AX
MOV AX,Counter
CMP TempJ,AX ;Meaning it's in last column
JE Fix
AddJ:
ADD TempJ,2 ;Move to next column
JMP SubNumbers
Fix:
MOV TempJ,0 ;Back to first column
ADD TempI,4 ;New row
SubNumbers:
MOV SI,WORD PTR [BP+6]
MOV ES,WORD PTR [BP+8]
ADD SI,TempI
MOV DI,WORD PTR ES:[SI]
MOV ES,WORD PTR ES:[SI+2]
ADD DI,TempJ
MOV AX,WORD PTR ES:[DI] ;AX contains number to check with N
MOV BX,N ;Move N to BX in order to save N's value
SUB BX,AX ;BX (N) -= AX
CMP BX,0
JG Continue2
Neg BX
Continue2:
MOV AX,Min
SUB AX,BX ;Substract former minimum and current sub result
CMP AX,0 ;To check which one is bigger
JLE Continue3 ;If BX > AX
MOV Min,BX ;Else, Min=BX
MOV SI,WORD PTR [BP+12] ;SI point to *num1
MOV GS,WORD PTR [BP+14] ;Segment of *num1
MOV AX,N
MOV GS:[SI],AX ;*num1 = N
MOV SI,WORD PTR [BP+16] ;SI point to *num2
MOV GS,WORD PTR [BP+18] ;Segment of *num2
MOV AX,WORD PTR ES:[DI] ;AX = second number
MOV GS:[SI],AX ;*num2 = second number
Continue3:
MOV AX,Counter
CMP TempJ,AX ;Meaning all columns were checked
JNE AddJ
MOV TempJ,0 ;Else, go to first column
ADD TempI,4 ;Next row
MOV AX,Counter
ADD AX,2
MUL Two
CMP TempI,AX ;Meaning all rows (and columns) were checked
JNE SubNumbers
MOV AX,Counter
ADD J,2 ;Move to next column with N number (J is pointing to INT so advance 2 bytes)
CMP J,AX
JNE GetN
Fix2:
MOV J,0
ADD I,4
MOV AX,Counter
ADD AX,2
MUL Two
CMP I,AX ;If all rows have been checked with N number (I is pointing to pointer so jumps of 4 byte, LARGE MODEL)
JE Finish
JMP GetN
Finish:
MOV AX,Min ;Save value to return
POP GS ;POP by LIFO order
POP ES
POP CX
POP DI
POP SI
POP BP
RET ;AX, IP and CS
_getDiffMin ENDP
END Start
在程序集 8086 中编写了一个程序,它将从 C 接收以下内容:
int *matrix[size], int size, int *num1, int *num2.
我最初将其作为小模型编写,效果很好,当我将其转换为大模型时它停止正常工作,我尝试更改循环计数,"rows pointer" 加 4,"columns pointer" 加 2(尝试加 4 和相反)。
程序应该检查最小值(绝对值),即最小的 |x-y|。 例如,该过程将得到 N 个数,从所有其他数中减去它并始终保存 |x-y| 的最小值。之后它将N个数字向前移动一个数字,并与其余数字进行相同的检查,直到所有矩阵都被检查。
C代码(这个不能改):
#include <stdio.h>
#include <stdlib.h>
extern int getDiffMin(int *mat[], int size , int *num1 , int *num2);
int main()
{
int
diff , i, j , num1 , num2;
int **mat = (int **)malloc(sizeof(int *) * 4);
for (i = 0; i < 4; i++)
mat[i] = (int *)malloc(sizeof(int) * 4);
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
mat[i][j] = (i*j) - (5 * i) - (14 * j);
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
printf("%d\t", mat[i][j]);
printf("\n");
}
diff = getDiffMin(mat, 4 , &num1 , &num2);
printf("\nminDiff == |(%d)-(%d)| = %d", num1 , num2 , diff);
for (i = 0; i < 4; i++)
free(mat[i]);
free(mat);
return 0;
}
汇编代码:
;extern int getDiffMin(int *mat[], int size , int *num1 , int *num2)
; BP+6+8 BP+10 BP+12+14 BP+16+18
;
.MODEL LARGE ;Pointers size = 4 bytes
.DATA
I DW ?
J DW ?
N DW ?
Min DW ?
TempI DW ?
TempJ DW ?
Counter DW ?
Two DW 2
.CODE
.386
PUBLIC _getDiffMin
_getDiffMin PROC FAR
Start:
PUSH BP ;Save BP's current value
MOV BP,SP
PUSH SI
PUSH DI
PUSH CX
PUSH ES
PUSH GS
MOV CX,WORD PTR [BP+10] ;CX point to size (matrix of size*size)
MOV SI,WORD PTR [BP+6] ;SI point to pointer in *mat[] (points to rows)
MOV ES,WORD PTR [BP+8] ;Segment of *mat[]
MOV DI,WORD PTR ES:[SI] ;DI point to value in *mat[] (points to columns, with first pointer on rows so gives value)
MOV ES,WORD PTR ES:[SI+2] ;Segment of *mat[]
MOV I,0 ;Rows index counter
MOV J,0 ;Columns index counter
MOV Counter,CX
ADD Counter,CX ;Counter for loop
FirstGetN: ;Get number to check with all other numbers
MOV AX,WORD PTR ES:[DI] ;AX has value which DI is pointing to
MOV N,AX
FirstSubNumbers:
ADD DI,2 ;Point to next column
MOV AX,WORD PTR ES:[DI] ;AX has value one column ahead from N
SUB AX,N
CMP AX,0
JG Continue1
NEG AX ;Convert sub result to positive
Continue1:
MOV Min,AX ;Save minimum difference in Min for loop with compare ahead
MOV SI,WORD PTR [BP+12] ;SI point to *num1 (in case first check had the minimum difference)
MOV GS,WORD PTR [BP+14] ;Segment of *num1
MOV AX,N
MOV GS:[SI],AX ;*num1 = N
MOV SI,WORD PTR [BP+16] ;SI point to *num2
MOV GS,WORD PTR [BP+18] ;Segment of *num2
MOV AX,WORD PTR ES:[DI] ;AX = second number
MOV GS:[SI],AX ;*num2 = second number
GetN:
MOV SI,WORD PTR [BP+6]
MOV ES,WORD PTR [BP+8]
ADD SI,I ;Add needed row
MOV DI,WORD PTR ES:[SI]
MOV ES,WORD PTR ES:[SI+2]
ADD DI,J ;Add needed column
MOV AX,WORD PTR ES:[DI]
MOV N,AX ;N contains number being checked with others
MOV AX,I ;In order to move from N location forward (numbers before were checked during the loop)
MOV TempI,AX
MOV AX,J
MOV TempJ,AX
MOV AX,Counter
CMP TempJ,AX ;Meaning it's in last column
JE Fix
AddJ:
ADD TempJ,2 ;Move to next column
JMP SubNumbers
Fix:
MOV TempJ,0 ;Back to first column
ADD TempI,4 ;New row
SubNumbers:
MOV SI,WORD PTR [BP+6]
MOV ES,WORD PTR [BP+8]
ADD SI,TempI
MOV DI,WORD PTR ES:[SI]
MOV ES,WORD PTR ES:[SI+2]
ADD DI,TempJ
MOV AX,WORD PTR ES:[DI] ;AX contains number to check with N
MOV BX,N ;Move N to BX in order to save N's value
SUB BX,AX ;BX (N) -= AX
CMP BX,0
JG Continue2
Neg BX
Continue2:
MOV AX,Min
SUB AX,BX ;Substract former minimum and current sub result
CMP AX,0 ;To check which one is bigger
JLE Continue3 ;If BX > AX
MOV Min,BX ;Else, Min=BX
MOV SI,WORD PTR [BP+12] ;SI point to *num1
MOV GS,WORD PTR [BP+14] ;Segment of *num1
MOV AX,N
MOV GS:[SI],AX ;*num1 = N
MOV SI,WORD PTR [BP+16] ;SI point to *num2
MOV GS,WORD PTR [BP+18] ;Segment of *num2
MOV AX,WORD PTR ES:[DI] ;AX = second number
MOV GS:[SI],AX ;*num2 = second number
Continue3:
MOV AX,Counter
CMP TempJ,AX ;Meaning all columns were checked
JNE AddJ
MOV TempJ,0 ;Else, go to first column
ADD TempI,4 ;Next row
MUL Two
CMP TempI,AX ;Meaning all rows (and columns) were checked
JNE SubNumbers
MOV AX,Counter
ADD J,2 ;Move to next column with N number (J is pointing to INT so advance 2 bytes)
CMP J,AX
JNE GetN
Fix2:
MOV J,0
MOV AX,Counter
MUL Two
ADD I,4
CMP I,AX ;If all rows have been checked with N number (I is pointing to pointer so jumps of 4 byte, LARGE MODEL)
JE Finish
JMP GetN
Finish:
MOV AX,Min ;Save value to return
POP GS ;POP by LIFO order
POP ES
POP CX
POP DI
POP SI
POP BP
RET ;AX, IP and CS
_getDiffMin ENDP
END Start
谢谢。
答案是我需要为 "loops" 添加 2,因为 'size'(来自 C 代码)从 0 开始计数。
这是 ASM 代码:
;extern int getDiffMin(int *mat[], int size , int *num1 , int *num2)
; BP+6+8 BP+10 BP+12+14 BP+16+18
;
.MODEL LARGE ;Pointers size = 4 bytes
.DATA
I DW ?
J DW ?
N DW ?
Min DW ?
TempI DW ?
TempJ DW ?
Counter DW ?
Two DW 2
.CODE
.386
PUBLIC _getDiffMin
_getDiffMin PROC FAR
Start:
PUSH BP ;Save BP's current value
MOV BP,SP
PUSH SI
PUSH DI
PUSH CX
PUSH ES
PUSH GS
MOV CX,WORD PTR [BP+10] ;CX point to size (matrix of size*size)
MOV SI,WORD PTR [BP+6] ;SI point to pointer in *mat[] (points to rows)
MOV ES,WORD PTR [BP+8] ;Segment of *mat[]
MOV DI,WORD PTR ES:[SI] ;DI point to value in *mat[] (points to columns, with first pointer on rows so gives value)
MOV ES,WORD PTR ES:[SI+2] ;Segment of *mat[]
MOV I,0 ;Rows index counter
MOV J,0 ;Columns index counter
MOV Counter,CX
ADD Counter,2 ;Since size starts from 0, need to make our "loop" bigger by 2
FirstGetN: ;Get number to check with all other numbers
MOV AX,WORD PTR ES:[DI] ;AX has value which DI is pointing to
MOV N,AX
FirstSubNumbers:
ADD DI,2 ;Point to next column
MOV AX,WORD PTR ES:[DI] ;AX has value one column ahead from N
SUB AX,N
CMP AX,0
JG Continue1
NEG AX ;Convert sub result to positive
Continue1:
MOV Min,AX ;Save minimum difference in Min for loop with compare ahead
MOV SI,WORD PTR [BP+12] ;SI point to *num1 (in case first check had the minimum difference)
MOV GS,WORD PTR [BP+14] ;Segment of *num1
MOV AX,N
MOV GS:[SI],AX ;*num1 = N
MOV SI,WORD PTR [BP+16] ;SI point to *num2
MOV GS,WORD PTR [BP+18] ;Segment of *num2
MOV AX,WORD PTR ES:[DI] ;AX = second number
MOV GS:[SI],AX ;*num2 = second number
GetN:
MOV SI,WORD PTR [BP+6]
MOV ES,WORD PTR [BP+8]
ADD SI,I ;Add needed row
MOV DI,WORD PTR ES:[SI]
MOV ES,WORD PTR ES:[SI+2]
ADD DI,J ;Add needed column
MOV AX,WORD PTR ES:[DI]
MOV N,AX ;N contains number being checked with others
MOV AX,I ;In order to move from N location forward (numbers before were checked during the loop)
MOV TempI,AX
MOV AX,J
MOV TempJ,AX
MOV AX,Counter
CMP TempJ,AX ;Meaning it's in last column
JE Fix
AddJ:
ADD TempJ,2 ;Move to next column
JMP SubNumbers
Fix:
MOV TempJ,0 ;Back to first column
ADD TempI,4 ;New row
SubNumbers:
MOV SI,WORD PTR [BP+6]
MOV ES,WORD PTR [BP+8]
ADD SI,TempI
MOV DI,WORD PTR ES:[SI]
MOV ES,WORD PTR ES:[SI+2]
ADD DI,TempJ
MOV AX,WORD PTR ES:[DI] ;AX contains number to check with N
MOV BX,N ;Move N to BX in order to save N's value
SUB BX,AX ;BX (N) -= AX
CMP BX,0
JG Continue2
Neg BX
Continue2:
MOV AX,Min
SUB AX,BX ;Substract former minimum and current sub result
CMP AX,0 ;To check which one is bigger
JLE Continue3 ;If BX > AX
MOV Min,BX ;Else, Min=BX
MOV SI,WORD PTR [BP+12] ;SI point to *num1
MOV GS,WORD PTR [BP+14] ;Segment of *num1
MOV AX,N
MOV GS:[SI],AX ;*num1 = N
MOV SI,WORD PTR [BP+16] ;SI point to *num2
MOV GS,WORD PTR [BP+18] ;Segment of *num2
MOV AX,WORD PTR ES:[DI] ;AX = second number
MOV GS:[SI],AX ;*num2 = second number
Continue3:
MOV AX,Counter
CMP TempJ,AX ;Meaning all columns were checked
JNE AddJ
MOV TempJ,0 ;Else, go to first column
ADD TempI,4 ;Next row
MOV AX,Counter
ADD AX,2
MUL Two
CMP TempI,AX ;Meaning all rows (and columns) were checked
JNE SubNumbers
MOV AX,Counter
ADD J,2 ;Move to next column with N number (J is pointing to INT so advance 2 bytes)
CMP J,AX
JNE GetN
Fix2:
MOV J,0
ADD I,4
MOV AX,Counter
ADD AX,2
MUL Two
CMP I,AX ;If all rows have been checked with N number (I is pointing to pointer so jumps of 4 byte, LARGE MODEL)
JE Finish
JMP GetN
Finish:
MOV AX,Min ;Save value to return
POP GS ;POP by LIFO order
POP ES
POP CX
POP DI
POP SI
POP BP
RET ;AX, IP and CS
_getDiffMin ENDP
END Start