书中demo求解

不担心 2016-03-20 02:39:18
section .bss
Buff resb 1

section .data

section .text
global _start

_start:
nop

Read: mov eax,3 l
mov ebx,0
mov ecx,Buff
mov edx,1
int 80h

cmp eax,0
je Exit

cmp byte [Buff],61h
jb Write
cmp byte [Buff],7Ah
ja Write

sub byte [Buff],20h

Write: mov eax,4
mov ebx,1
mov ecx,Buff
mov edx,1
int 80h
jmp Read

Exit: mov eax,1
mov ebx,0
int 80H

这个是书本中的一个例子,功能是读入一个文本,然后将所有的小写转换为大写,运行非常正常,没有问题.
我不明白的是在read标签处通过
mov ecx,Buff ; Pass offset of the buffer to read to
mov edx,1 ; Tell sys_read to read one char from stdin
命令读入一个字节,那么在write标签处jmp 到read处,再次执行的时候为什么会读取下一个字节呢?buff的地址并没有变,中间也没有计算器指明偏移量,应该读取还是原来的那个字符才对,请大大们帮忙解释一下.谢谢!
...全文
219 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
fornetuse123 2016-03-23
  • 打赏
  • 举报
回复
上面的reand子程序 代码循环代码错误了,临时缓冲区基址因该换个寄存器不用ecx就好了。反正就是那么个意思。
fornetuse123 2016-03-23
  • 打赏
  • 举报
回复
终于想明白了, int80应该是这样的代码: cmp ebx,0 je readentry cmp ebx,1 je writeentry iret readentry:push ecx push edx call readstdin pop edx pop ecx iret writeentry: push ecx push edx call writestndout pop edx pop ecx iret 也就是说int80还需要调取一个读或者写子程序。 readstndin是这样的。 read:push ecx move ecx,edx ;将需要读入临时缓冲区的字节数用来计数循环,因为临时缓冲区基地址保存在ecx中,所以要 先入栈保护 move eax,[bx ] ;bx为标准输入缓冲区基地址 cmp eax,0 ;0为字符串结束标志 je exit pop ecx mov byte ptr[ecx],eax ;往临时缓冲区写数据 inc ecx ;临时定义缓冲区指针移位 inc bx ;标准输入缓冲区基地址指针移位 loop read exit: ret 也就是说,int80只是用来调度读写操作和给相应子程序传递参数的,而真正的读或者写子程序负责往临时缓冲区读或者写数据,并调整指针。
不担心 2016-03-23
  • 打赏
  • 举报
回复
fornetuse123 2016-03-22
  • 打赏
  • 举报
回复
昨晚我又想了想 如果缓冲区是堆栈的话,就简单实现了。 mov ebx,0 ;从原始文件stdin的缓冲区,告诉int80子程序ss段基址和sp指针 mov ecx,Buff ;读取内容存放到buff mov edx,1 ;从从原始文件stdin的缓冲区当前指针处读取1个字节,存放到buff int 80h 这样int80子程序只要根据edx中的数字进行计数循环,pop edx中的数字次到buff开始的0+edx中的数字个字节内存中去(假设buff内存区足够大) 这样,应用程序就不用申请系统对缓冲区进行管理,大大降低系统开销和效率。 但是,有个问题,缓冲区的这个堆栈是不是专用的呢?如果不是专用,那么在另外的线程也使用该堆栈时,如果执行了push或pop操作,那么,现在的线程再读取到的堆栈内容其实不是想需要的。这怎么处理
赵4老师 2016-03-21
  • 打赏
  • 举报
回复
在DosBox下使用TurboDebug单步调试。 bc++3.1 http://download.csdn.net/source/2805028
  • 打赏
  • 举报
回复
程序没有问题。 linux int 80h是系统调用,eax=3是sys_read,ebx=file descriptor(0---stdin,1---stdout),eax=4是sys_write。stdin、stdout是流式设备(DOS、Windows中叫字符设备),不需要也不能显式移动文件指针,每次访问后会自动移动。
fornetuse123 2016-03-21
  • 打赏
  • 举报
回复
我明白这段代码的意思了,楼主你大概这段代码少抄了一段吧 那就是Tell sys_read to read one char from stdin中的sadin这一段 这段程序的功能因该是你在键盘中输入一个非0字符,每次只能输一个,你输多了也没用,程序每次只显示一个。 如果输入0,程序就结束了 如果输入不是大小写字母,程序直接显现该字符 如果输入是小写字母,程序转换为大写字母输出。 楼主你看书能不能仔细点,书中有说输出一段文本字符么?另外标准输入设备那一段,你忘记抄也不对吧
fornetuse123 2016-03-21
  • 打赏
  • 举报
回复
还有这句 cmp eax,0 je Exit 那不是这个程序死循环了么。我怎么看永远不会eax=o呢
不担心 2016-03-21
  • 打赏
  • 举报
回复
我也觉得应该是系统内部有个读取缓冲区的指针,每次读取固定长度的内容之后,指针就停留在最后读取的地方,之后接着往后读取
可能是这样
fornetuse123 2016-03-21
  • 打赏
  • 举报
回复
引用 1 楼 zara 的回复:
每次处理,就是一个字符,总是放到 buff 这里的;后面的字符会把前面的覆盖了,所以程序的最后,程序里是没有完整的输入的字符串的,即便是在屏幕上显示了。
这段代码我也有同样疑问呀?即便覆盖原来,那它读原buffde时候,没有增加偏移量,那不是还读的同一个位置么 ?那显示的不就是同一个字么这次大写,下次小写循环了。怎么会读取一段字符的
zara 2016-03-21
  • 打赏
  • 举报
回复
每次处理,就是一个字符,总是放到 buff 这里的;后面的字符会把前面的覆盖了,所以程序的最后,程序里是没有完整的输入的字符串的,即便是在屏幕上显示了。
fornetuse123 2016-03-21
  • 打赏
  • 举报
回复
不对,还应该是系统来管理缓冲区指针,否则如果缓冲区是链队列逻辑结构的话,int80好像没那么大能力。 应该就是:缓冲区内容在被读取后,指针被系统移动相应字节位置,即缓冲区内容不是静态不变的
fornetuse123 2016-03-21
  • 打赏
  • 举报
回复
实际上,读取原始文件stdin的缓冲区的参数中,edx的取值范围是1-缓冲区长度,如果int80中没有功能为将point-> stdin头指针指向->next这样的语句,他怎么实现读取任意长度的缓冲区字节内容了?在这里,系统在文件被读入缓冲区后,应该已经将控制权交还给应用程序,所以最大的可能就是:int80有自动更改缓冲区指针的功能 Read: mov eax,3 l mov ebx,0 ;从原始文件stdin的缓冲区 mov ecx,Buff ;读取内容存放到buff mov edx,1 ;从从原始文件stdin的缓冲区当前指针处读取1个字节,存放到buff int 80h
fornetuse123 2016-03-21
  • 打赏
  • 举报
回复
根据几位大神的解说,加上百度,不知道我这样理解的对不对: 你说你是将一个原始文件读入,然后转换为大写输出到另一个文件了 这个程序的作用是这样的,首先一个重点:系统读写一个文件都要先创建一个缓冲区, 这里,程序先从原始文件stdin的缓冲区里取1个字节的内容,存放到你定义的一个字节的buff内存中,这里buff内存和原始文件stdin的缓冲区是两块不同的内存,但是这块buff内存是写大写输出到另一个文件的缓冲区。 当你从原始文件stdin的缓冲区里取1个字节后,Read: mov eax,3 l mov ebx,0 ;从原始文件stdin的缓冲区 mov ecx,Buff ;读取内容存放到buff mov edx,1 ;从从原始文件stdin的缓冲区当前指针处读取1个字节,存放到buff int 80h 系统会将原始文件stdin的缓冲区里的内存指针指向下一个字节,除非你读完了缓冲区最后一个字节,这时,应该是一个空指针。其实我感觉最大的可能是,int80这个中断子程序里就含有功能为将point-> stdin头指针指向->next这样的语句,否则不可能实现读写文件。但是我们看不到int80内部代码 我们两个的误区在于:认为自己定义的buff是原始文件stdin的缓冲区,其实它只不过是每次从原始文件stdin的缓冲区读取了一个字节而已。相应,他每次向另一个文件写入一个字节。
  • 打赏
  • 举报
回复
stdin是标准输入,典型例子就是键盘。
  • 打赏
  • 举报
回复
Read: mov eax,3 mov ebx,0 mov ecx,Buff mov edx,1 int 80h 从stdin读一个字符存在Buff里。stdin就象水龙头,每次打开放出来的都是不同的水(当然也可能没水),是系统在内部维护一个缓冲区,每读一次就取走一部分,系统会自动移动文件指针。
不担心 2016-03-21
  • 打赏
  • 举报
回复
引用 4 楼 fornetuse123 的回复:
我明白这段代码的意思了,楼主你大概这段代码少抄了一段吧 那就是Tell sys_read to read one char from stdin中的sadin这一段 这段程序的功能因该是你在键盘中输入一个非0字符,每次只能输一个,你输多了也没用,程序每次只显示一个。 如果输入0,程序就结束了 如果输入不是大小写字母,程序直接显现该字符 如果输入是小写字母,程序转换为大写字母输出。 楼主你看书能不能仔细点,书中有说输出一段文本字符么?另外标准输入设备那一段,你忘记抄也不对吧
section .bss
	Buff resb 1

section .data

section .text
	global _start

_start:
	nop            ; This no-op keeps the debugger happy

Read:	mov eax,3      ; Specify sys_read call
	mov ebx,0      ; Specify File Descriptor 0: Standard Input
	mov ecx,Buff   ; Pass offset of the buffer to read to
	mov edx,1      ; Tell sys_read to read one char from stdin
	int 80h        ; Call sys_read

	cmp eax,0	; Look at sys_read's return value in EAX
	je Exit		; Jump If Equal to 0 (0 means EOF) to Exit
			; or fall through to test for lowercase
	cmp byte [Buff],61h  ; Test input char against lowercase 'a'
	jb Write	; If below 'a' in ASCII chart, not lowercase
	cmp byte [Buff],7Ah  ; Test input char against lowercase 'z'
	ja Write	; If above 'z' in ASCII chart, not lowercase
			; At this point, we have a lowercase character
	sub byte [Buff],20h  ; Subtract 20h from lowercase to give uppercase...
			; ...and then write out the char to stdout
Write:  mov eax,4	; Specify sys_write call
	mov ebx,1	; Specify File Descriptor 1: Standard output
	mov ecx,Buff	; Pass address of the character to write
	mov edx,1	; Pass number of chars to write
	int 80h		; Call sys_write...
	jmp Read	; ...then go to the beginning to get another character

Exit:	mov eax,1	; Code for Exit Syscall
	mov ebx,0	; Return a code of zero to Linux
	int 80H		; Make kernel call to exit program
这是完整的带注释的代码,我不知道你说的漏了什么 这段代码我编译运行过了,没问题,功能是是读取一个文本文件,将所有小写转成大写保存到另一个文件 ./uppercase1 < xxx.txt > xxxUp.txt
不担心 2016-03-21
  • 打赏
  • 举报
回复
引用 5 楼 DelphiGuy 的回复:
程序没有问题。 linux int 80h是系统调用,eax=3是sys_read,ebx=file descriptor(0---stdin,1---stdout),eax=4是sys_write。stdin、stdout是流式设备(DOS、Windows中叫字符设备),不需要也不能显式移动文件指针,每次访问后会自动移动。
虽然我不懂,但是我觉得你说的是对的,能详细解释一下吗? 调用了80中断后 mov ecx,Buff mov edx,1 这两句为什么会读取后面一个字节?

21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧