注册 登录
编程论坛 汇编论坛

请教一下子函数调用和字符串的问题!

cnlkf 发布于 2008-11-18 11:48, 4519 次点击
我在做一道字符串加密题,在函数调用的时候提示出错了,而且不能将字符串从ESI里MOV到一个空字符串里,下面是我程序出错的部分

.if eax==1001
mov eax,wParam
.if eax==1001
mov bz,0
.if eax==1002
mov bz,1
invoke mm,addr s1,addr s2,bz  这里在调用的时候提示出错了,但又不知道哪里出问题了。


子函数在这里:
mm proc s1:DB,s2:db,bz:db   这句提示出错:
                            instruction or register not accepted in current CPU mode
cmp bz,0
je jiami
jmp jiemi
jiami:
mov esi,offset s
mov s1,[esi]   这里提示:invalid instruction operands
shl s1,1
add s1,3
inc byte typ[esi]   
cmp [esi],0   这里提示:invalid instruction operands
je L2
jmp jiami
jiemi:
mov esi,offset s1
mov s2,[esi]   也是:invalid instruction operands
sub s2,3
shr s2,1
inc byte typ[esi]   
cmp [esi],0   也是: invalid instruction operands
je L2
jmp jiemi
L2:ret
mm endp   这里提示:instruction or register not accepted in current CPU mode

数据在这里
s DB "hello",0
s1 db 20 dup(?)
s2 db 20 dup(?)
bz db ?
请问到底是哪里出问题了,怎么用mov s1,esi会提示出错呢?子函数应该怎么调用,我现在刚学汇编不久很多都看不懂,希望有人帮忙解释一下,感激不尽.
22 回复
#2
zklhp2008-11-18 12:52
你先理解一下它说的意思呀

mm proc s1:DB,s2:db,bz:db   这个明显有错 因为你给它的是指针 就是一个地址 是32位呀 就是一个双字 你这个当然不对了

win32下api压栈都是压双字吧

后面几个也是这个错  错误理解了指针 之类的概念

mov esi,offset s

这个执行后 esi中放的是字符串 s 就是 "hello",0  第一个字符的首地址 注意 是地址 就是个双字!!!
#3
zklhp2008-11-18 12:54
建议你联系一下c语言里的指针

说实话 要是你直接学汇编可能很难 有c的基础就好点

对指针要深刻理解

偶说的可能不太明白 大概就这意思
#4
zklhp2008-11-18 12:58
[bo][un]cnlkf[/un] 在 2008-11-18 11:48 的发言:[/bo]

我在做一道字符串加密题,在函数调用的时候提示出错了,而且不能将字符串从ESI里MOV到一个空字符串里,下面是我程序出错的部分

.if eax==1001
mov eax,wParam
.if eax==1001
mov bz,0
.if eax==1002
mo ...


说白了 就是对字符串的理解不够深刻 不知道如何处理字符串

要知道 汇编比较底层 有些东西要深刻理解 可不像vb那样啊
#5
cnlkf2008-11-18 13:51
我知道你的意思,我学过C,虽然不是很好,但对指针跟地址有点理解,你说
mm proc s1:DB,s2:db,bz:db  这里的地址调用我知道,是传递字符串的首地址过来,但是我不清楚汇编中指针是多少位,这里是不是可以把类型改成32位就行了?
还有从主函数
invoke mm,addr s1,addr s2,bz  
这里调用的时候就已经提示出错了,我就搞不懂是哪里出问题。

这里的 mov esi,offset s 我看得懂,知道是传递字符串的首地址,但是在执行
mov s1,[esi]  的意思不是将esi中的第一个字符的地址赋给s1吗?也要将s1改32位?

在汇编里的指针操作全都是32位的吗?那定义个8位变量是不是就不能进行指针操作?
还有像这样的题要怎么对字符串进行传递呢?

这道题用C和C++做起来很简单,我也做过,只是现在刚学汇编不久,对堆栈和汇编里的一些语句会看不明白什么意思。
#6
ONEPROBLEM2008-11-18 18:12
这个程序出错的地方还蛮多了.方便的话,建议LZ把整个源程序都贴出来~~
我发现几个地方要修改一下:
1.mov s1,[esi]
  mov s2,[esi]
之类的指令是错误的,两个操作数都是内存是不行的,要用一个寄存器过渡一下.
可以这样:
lea edi,s1    ;把s1的有效地址装入edi
mov eax,[esi] ;如果进行字节操作,注意用al
mov [edi],eax
其它类推;
2.  cmp [esi],0 这种比较指令,其中得有一个是寄存器.
可以这样:
mov al,[esi] ;进行字操作的话就用ax,类推
cmp al,0
3.对于子程序的调用,除了参数要正确之外,还得注意保存一些重要的寄存器.
可以在子程序调用时,用pushad 和popad这两条指令.
#7
cnhanxiao2008-11-18 18:54
回复 5# 的帖子
mm proc s1:DB,s2:db,bz:db

mm proc s1:DWORD,s2:DWORD,s3:DWORD

因为参数都是靠堆栈传递进来的,所以参数都是32位的。
#8
cnlkf2008-11-19 07:58
感谢ONEPROBLEM 的指点,不过现在在调用子函数的时候还是老问题,不知道什么原因,
我已经照cnhanxiao改了几个行参的类型,不过还是执行提示失败了...在汇编调用子函数需要怎么设置才能调用呢?是不是在传递地址的时候一定要把行参改为32位的?

我用radasm画了两个按钮,在点两个按钮的时候就激发这个过程,整个原程序在这里:


    mm proc s1:DWORD,s2:DWORD,s3:DWORD
        cmp bz,0
        je jiami
        jmp jiemi
  jiami:
        mov esi,offset s
        lea edi,s1    ;把s1的有效地址装入edi
        mov al,[esi] ;如果进行字节操作,注意用al
        mov [edi],al
        shl s1,1
        add s1,3
        inc byte ptr [esi]
        mov al,[esi] ;进行字操作的话就用ax,类推
        cmp al,0
        je L2
        jmp jiami
  jiemi:
        mov esi,offset s1
        lea edi,s2    ;把s1的有效地址装入edi
        mov al,[esi] ;如果进行字节操作,注意用al
        mov [edi],al
        sub s2,3
        shr s2,1
        inc byte ptr [esi]
        mov al,[esi]
        cmp al,0
        je L2
        jmp jiemi
     L2:ret
     mm endp
;########################################################################

DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    mov        eax,uMsg
    .if eax==WM_INITDIALOG

    .elseif eax==WM_COMMAND
        mov  eax,wParam
        .if eax==1001 ;1001是按钮1
        mov  eax,wParam
        .if eax==1001
            mov bz,0            
        .if eax==1002  ;1002是按钮2
            mov bz,1
            invoke mm,addr s1,addr s2,bz
            invoke MessageBox,hWin,addr mess1, addr mtl,MB_OK            
        .endif
        .endif
        .endif
    .elseif eax==WM_CLOSE
        invoke EndDialog,hWin,0
    .else
        mov        eax,FALSE
        ret
    .endif
    mov        eax,TRUE
    ret

DlgProc endp

end start

数据在这里:

.data
mtl    db    "test my titles",0
mmsg db    "hello world!",0
s DB "hello",0
s1 dd 20 dup(0)
s2 dd 20 dup(0)
bz db ?
#9
ONEPROBLEM2008-11-19 08:14
建议LZ贴出完整的程序~~
程序从哪里开始,start呢?
程序什么时候退出,exitprocess呢?
#10
cnlkf2008-11-19 09:57
抱歉,早上因为要上课,所以急急忙忙没弄好...
我是用radasm,里面有三个工程组,一个.asm一个.inc还有一个窗口按钮.
这是asm文件:
.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include text1.inc

.code

start:

    invoke GetModuleHandle,NULL
    mov        hInstance,eax

    invoke InitCommonControls
    invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
    invoke ExitProcess,0
    mm proc s1:DWORD,s2:DWORD,s3:DWORD
        cmp bz,0
        je jiami
        jmp jiemi
  jiami:
        mov esi,offset s
        lea edi,s1    ;把s1的有效地址装入edi
        mov al,[esi] ;如果进行字节操作,注意用al
        mov [edi],al
        shl s1,1
        add s1,3
        inc byte ptr [esi]
        mov al,[esi] ;进行字操作的话就用ax,类推
        cmp al,0
        je L2
        jmp jiami
  jiemi:
        mov esi,offset s1
        lea edi,s2    ;把s1的有效地址装入edi
        mov al,[esi] ;如果进行字节操作,注意用al
        mov [edi],al
        sub s2,3
        shr s2,1
        inc byte ptr [esi]
        mov al,[esi]
        cmp al,0
        je L2
        jmp jiemi
     L2:ret
     mm endp
;########################################################################

DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    mov        eax,uMsg
    .if eax==WM_INITDIALOG

    .elseif eax==WM_COMMAND
        mov  eax,wParam
        .if eax==1001
        mov  eax,wParam
        .if eax==1001
            mov bz,0            
        .if eax==1002
            mov bz,1
            invoke mm,addr s1,addr s2,bz
            invoke MessageBox,hWin,addr mess1, addr mtl,MB_OK            
        .endif
        .endif
        .endif
    .elseif eax==WM_CLOSE
        invoke EndDialog,hWin,0
    .else
        mov        eax,FALSE
        ret
    .endif
    mov        eax,TRUE
    ret

DlgProc endp

end start

这是.inc文件

include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
include D:\masm32\新建文件夹\RadASM\masm\inc\radbg.inc
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib

DlgProc            PROTO    :HWND,:UINT,:WPARAM,:LPARAM

.const

IDD_DIALOG1            equ 101

;#########################################################################

.data?

hInstance            dd ?

;#########################################################################
.data
mtl    db    "test my titles",0
mmsg db    "hello world!",0
s DB "hello",0
s1 dd 20 dup(0)
s2 dd 20 dup(0)
bz db ?
mess1 db "finished(XxY+Z-V)/P!",0
#11
swp1601082008-11-19 11:03
感觉错误很多
mov al,[esi] 直接这么写不行把 mov al,byte ptr [esi]

感觉基础太差 多看书把
#12
ONEPROBLEM2008-11-19 11:14
invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
;==================
我用的编译器和你不一样,没法上机验证.
你先修改这个地方试试看吧:
 invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,offset DlgProc,NULL
#13
ONEPROBLEM2008-11-19 11:21
[bo][un]swp160108[/un] 在 2008-11-19 11:03 的发言:[/bo]

感觉错误很多
mov al,[esi] 直接这么写不行把 mov al,byte ptr [esi]

感觉基础太差 多看书把

这点倒是不要紧的~~
因为al 寄存器已经指明进行的是字节操作~~主要是在没有寄存器参与的情况下要指明操作的数据长度~~
#14
cnlkf2008-11-19 11:23
请问ONEPROBLEM你是用什么编译器的?我这个也用得很不舒服,很多地方都用不熟悉,你能不能发你那个给我一下?还有这道题现在的问题是在调用子函数提示出错,我把子函数直接搬到主函数里,但是运行的时候还是没结果,你能不能帮我看一下是哪里出问题?

    mm proc s1:DWORD,s2:DWORD,s3:DWORD
        cmp bz,0
        je jiami
        jmp jiemi
  jiami:
        mov esi,offset s
        lea edi,s1   
        mov al,[esi]
        mov [edi],al
        shl s1,1
        add s1,3
        inc byte ptr [esi]
        mov al,[esi]
        cmp al,0
        je L2
        jmp jiami


  jiemi: ;这是解密
        mov esi,offset s1
        lea edi,s2   
        mov al,[esi]
        mov [edi],al
        sub s2,3
        shr s2,1
        inc byte ptr [esi]
        mov al,[esi]
        cmp al,0
        je L2
        jmp jiemi
     L2:ret
     mm endp

这道题是根据bz的值对字符串s进行加密和解密,加密的方法为*2+3.
加密的字符串放到S1解密的放S2...最后调用一个窗口显示出字符串...
我设置两个按钮,根据按钮给BZ赋值,0就加密,1就解密..s是原来字符串,s1是加密后字符串,s2是存放解密后字符串(就是s1解密后的).
#15
ONEPROBLEM2008-11-19 11:32
;=========================================
           .386
           .model flat, stdcall  ;32 bit memory model
           option casemap :none  ;case sensitive

           include text1.inc

          .code

start:

    invoke GetModuleHandle,NULL
    mov        hInstance,eax

    invoke InitCommonControls
    invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
                                                 ;addr 只能向前引用,不能向后引用,应改为offset
    invoke ExitProcess,0
    mm proc s1:DWORD,s2:DWORD,s3:DWORD
        cmp bz,0              ;cmp指令的使用,必须有寄存器的参与
        je jiami
        jmp jiemi
  jiami:
        mov esi,offset s
        lea edi,s1    ;把s1的有效地址装入edi
        mov al,[esi] ;如果进行字节操作,注意用al
        mov [edi],al
        shl s1,1             ;错误,shl只能处理寄存器或内存单元中的数据,S1是个数据区
        add s1,3
        inc byte ptr [esi]
        mov al,[esi] ;进行字操作的话就用ax,类推
        cmp al,0
        je L2
        jmp jiami
  jiemi:
        mov esi,offset s1
        lea edi,s2    ;把s1的有效地址装入edi
        mov al,[esi] ;如果进行字节操作,注意用al
        mov [edi],al
        sub s2,3
        shr s2,1
        inc byte ptr [esi]
        mov al,[esi]
        cmp al,0
        je L2
        jmp jiemi
     L2:ret
     mm endp
;########################################################################

DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    mov        eax,uMsg
    .if eax==WM_INITDIALOG

    .elseif eax==WM_COMMAND
        mov  eax,wParam
        .if eax==1001
        mov  eax,wParam
        .if eax==1001
            mov bz,0            
        .if eax==1002
            mov bz,1
            invoke mm,addr s1,addr s2,bz
            invoke MessageBox,hWin,addr mess1, addr mtl,MB_OK            
        .endif
        .endif
        .endif
    .elseif eax==WM_CLOSE
        invoke EndDialog,hWin,0
    .else
        mov        eax,FALSE
        ret
    .endif
    mov        eax,TRUE
    ret

DlgProc endp

end start

这是.inc文件

include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
include D:\masm32\新建文件夹\RadASM\masm\inc\radbg.inc
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib

DlgProc            PROTO    :HWND,:UINT,:WPARAM,:LPARAM

.const

IDD_DIALOG1            equ 101

;#########################################################################

.data?

hInstance            dd ?

;#########################################################################
.data
mtl    db    "test my titles",0
mmsg db    "hello world!",0
s DB "hello",0
s1 dd 20 dup(0)
s2 dd 20 dup(0)
bz db ?
mess1 db "finished(XxY+Z-V)/P!",0
#16
ONEPROBLEM2008-11-19 11:38
编译器请到AOGO网站去下载他的MASMPlus,这个比较顺手.
不会用的话,先下载他的"汇编通讯",里面有所讲述的~~
你的这个程序并不难,问题是你对汇编指令不够清楚,建议查查"汇编指令表"!
当然,先打好基础比较重要~~
#17
zklhp2008-11-19 12:36
[bo][un]ONEPROBLEM[/un] 在 2008-11-19 11:38 的发言:[/bo]

编译器请到AOGO网站去下载他的MASMPlus,这个比较顺手.
不会用的话,先下载他的"汇编通讯",里面有所讲述的~~
你的这个程序并不难,问题是你对汇编指令不够清楚,建议查查"汇编指令表"!
当然,先打好基础比较重要~~


同意!
#18
cnlkf2008-11-19 13:06
呵呵,两位版主说得对,我对汇编的指令确实很多都不够清楚,只是这道题做了好几天了,都是根据书上的指令做的,现在想先把题做完,再边看书理解那些意思,不然看完之后我怕又给忘了..
#19
zklhp2008-11-19 13:08
[bo][un]cnlkf[/un] 在 2008-11-19 13:06 的发言:[/bo]

呵呵,两位版主说得对,我对汇编的指令确实很多都不够清楚,只是这道题做了好几天了,都是根据书上的指令做的,现在想先把题做完,再边看书理解那些意思,不然看完之后我怕又给忘了..


关键是对这些东西的理解 掌握

多向那他们请教吧 呵呵
#20
cnlkf2008-11-19 13:20
呵呵,我会用心去学的,zklhp版主和ONEPROBLEM版主能不能把你们两位的Q给我,如果有不懂可以请教一下,我现在刚学不久,想不遇到不懂的地方可以找个人探讨一下..
#21
ONEPROBLEM2008-11-19 15:19
[bo][un]cnlkf[/un] 在 2008-11-19 13:20 的发言:[/bo]

呵呵,我会用心去学的,zklhp版主和ONEPROBLEM版主能不能把你们两位的Q给我,如果有不懂可以请教一下,我现在刚学不久,想不遇到不懂的地方可以找个人探讨一下..

老弟,有问题发到论坛上来!大家都来帮助你岂不更好?
想把版主"占为己有"可不好啊~~ 开玩笑而已
#22
cnlkf2008-11-19 17:36
呵呵,也行那,就是怕有时看不到你们老人家在,找不到人问了那..
现在我整个程序重新修改了一下,但不知道为什么运行后那个调用显示字符的框没有出现,麻烦重新帮我看一下是哪里问题.
子函数:
string proc str1:DWORD,str2:DWORD,bz1:DWORD
        cmp bz1,0
        je jiami
        jmp jiemi
  jiami:
        mov esi,offset s
        lea edi,str1    ;把s1的有效地址装入edi
        mov al,[esi] ;如果进行字节操作,注意用al
        cmp al,0
        je L1
        shl al,1
        add al,3
        mov [edi],al
        inc byte ptr [esi]
        inc byte ptr [edi]
        mov al,[esi] ;进行字操作的话就用ax,类推
        jmp jiami
        
  jiemi:
        lea esi,str1
        lea edi,str2    ;把s1的有效地址装入edi
        mov al,[esi] ;如果进行字节操作,注意用al
        sub al,3
        shr al,1
        mov [edi],al
        inc byte ptr [edi]
        inc byte ptr [esi]
        mov al,[esi]
        cmp al,0
        je L2
        jmp jiemi
     L1:
        mov [edi],al
        invoke MessageBox,0,addr str1,addr mtl,MB_OK
     L2:
        mov [edi],al
        invoke MessageBox,0,addr str2,addr mtl,MB_OK
string endp

从主函数调用的地方:
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    mov        eax,uMsg
    .if eax==WM_INITDIALOG

    .elseif eax==WM_COMMAND
        mov  eax,wParam
        .if eax==1001
        mov  eax,wParam
        .if eax==1001
            mov bz,0    
            invoke string,addr s,addr s1,bz     
        .if eax==1002
            mov bz,1
            invoke string,addr s1,addr s2,bz            
        .endif
        .endif
        .endif
    .elseif eax==WM_CLOSE
        invoke EndDialog,hWin,0
    .else
        mov        eax,FALSE
        ret
    .endif
    mov        eax,TRUE
    ret

DlgProc endp

顺便弱弱的说句:原来mm是属于关键字的,汗.....
#23
zklhp2008-11-20 15:56
[bo][un]cnlkf[/un] 在 2008-11-19 13:20 的发言:[/bo]

呵呵,我会用心去学的,zklhp版主和ONEPROBLEM版主能不能把你们两位的Q给我,如果有不懂可以请教一下,我现在刚学不久,想不遇到不懂的地方可以找个人探讨一下..


偶的联系方式很公开吧 自己找就行 不过偶一般不在线

可以在qq上问含笑老大 他在线时间长~~~
1