※※只要解决问题就是高手※※进者有分!!!(100分)

  • 主题发起人 newsea008
  • 开始时间
来者有分
我顶
 
OK 。
1.“定义C: WORD:=$00FF,编译出错”的回答:注意我在代码里面不是这样写的,而是如下:
Const
C:Word=$00FF
// 其中没有冒号,并且上面需要做 Const 定义。
2.关于“打印文件”取内容的回答:
①如果“打印文件”是一个 ASCII 文件,请使用 string 操作提取。
②如果“打印文件”是一个 Binary 文件,请使用 stream 操作提取。
Binary 的话,取出一个完整片段后,请使用位操作处理,比如:$A4 E505 FA04 这个值,
对应可以定义为 $00 0000 0000 ,就是8位,16位,16位,总共40位长度。假如我需要取
其中的头8位,我可以使用 Mask 来取得:
$A4 E505 FA04 // <---- 需要操作的值
and $FF 0000 0000 // <---- Mask 值,最前面的是 与操作符 (and)
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
结果 $A4 0000 0000 // <---- 与操作后获得的结果
按照这个方法,我可以取到任意的位,取到结果后,我使用位移动操作,把它右移动 32 位
后,就是我要的值:Result:=Byte($A400000000 shr 32) 。
 
按这个思路,连 Mask 操作都可以省略,直接移位操作也可以做到。
另外,谁在提倡使用“汇编”?我看如果这种问题都使用汇编的话,
微软在中国登陆都困难!还有人会用外国佬的系统软件?
 
呵呵,你说了半天,不知道是我水平太低还是你没有描述清楚,我还是看不懂:
①“把X左移一位后得到的数X'与累加器里的数相加后得到X''”:我的理解就是 X'':=X'*2
因为,X 左移后累加器里就是这个左移后的值,把它和累加器内容相加就是乘以2的关系。
②“若X''最高位有溢出则X坐标-1”:最高位的最小值是0,最大值是1。哪一个算是溢出?

我认为,假如你对数制不是很清楚,对计算机内部工作不是很熟悉的话,尽量不要硬逼着自
己使用计算机的描述来说你的问题,只需要使用平常的语言来表达就可以了,比如描述为:
我想知道数据里 X 坐标的位移情况,或者,我想由取得的数值控制某个类打印机的东西。
——因为,我猜你在做打印机模拟器之类的东西,试图通过解析打印数据还原文字。
 
小雨哥,能知道你的邮箱吗?我的邮箱是newsea008@126.com。我想跟你再具体聊聊。再向你请教请教。我的QQ284166112
 
Sorry。我已经不写代码了。有问题请在论坛发表,好吗?
 
这种问题才适合使用嵌入汇编,
1.优化编码,就这个问题我想绝对可以优化的,比如你的HexToInt,而且还是函数调用
2.问题简单。才可能优化
不过重点在实现,用PAS实现之后再改用汇编优化比较合适
 
小雨哥,好。我说得不太清楚,是这样:
PRTBiaoPai.PRT中的数据含义如下:
00000000H:E3 9C A4 02 00 B7 02 A2 26 00 D5 00 AE 01 08 00;
00000010H:B0 A3 00 03 00 08 A2 05 00 23 E5 A6 B6 02………….
1.E3 9C是命令参数。
E0—Z、R轴都无效
E1—Z轴有效
E2—R轴有效
E3—Z、R轴有效
E4—置测试状态,0111回应
E5—标记机重置状态,1010回应
E6—测试打印完成,1001表示打印结束,0110表示正在打印
E7—清除打印命令,1010回应
E8—打印命令,1010回应
E9—测试是否打印,1001表示打印,0110表示不打印

原点校对:命令高4位为9或C(打印时作为回原点命令)(9—R轴正向回原点,C—R轴反向回原点)
D3 D2
0 0—平面不校对
0 1—平面校对,先X后Y
1 0—平面校对,先Y后X
1 1—平面校对,X、Y同时运动
D1 D0
0 0—平面校对
0 1—Z轴校对
1 0—R轴校对
1 1—Z轴、R轴校对

打印数据:
X、Y轴数据:命令高4位为A+数据(4字节)
D3—抬、落笔;0—抬笔,1—落笔
D2—速度选择;0—移动速度,1—打印速度
D1—Y轴方向;0—正向,1—反向
D0—X轴方向;0—正向,1—反向

2.取△X、△Y数据,存入缓冲区作为终点判据.
3.把△X、△Y分别左移一位得到△X’、△Y’。
4.再设置两个变量C1、C2,C1=$00FF,C2=$00FF。
5.△X’+ C1赋值给C1,若C1>=$10000,则X轴走一步(给X轴发一次脉冲),△X-1,然后△X'+(△X'+C1)赋值给C1.重复以上操作。若C1< $1000,△X不变,然后△X'+(△X'+C1)赋值给C1.则重复以上操作,直到△X减到0为止。△Y做同样的工作。
6.做完一次后,若取得是A4 02 00 B7 02.下一次取A2 26 00 D5 00。依次做下去。直到把PRTBiaoPai.PRT中的数据取完为止。

再次请教小雨哥!!!
 
你需要的关键是取得走步计算,其他内容假设你已经完成,那么我的提示如下:
假设:command -- 指令码;x_axis -- x 轴数据;y_axis -- y 轴数据,和数据已经被定义:
type
prtData=record
command:byte;
x_axis:word;
y_axis:word;
end;
PprtData=^prtData;

那么:
var // 全局
userBreak:Boolean

var // 局部
pdata:pprtData;
dx,dy:word;
c1,c2:word;
begin
repeat
dx:=pdata^.x_axis;
c1:=(dx shl 1)+$FF;
if c1>=$10000 then
begin
①... ---> (send x axis go forward);
if userBreak then
②---> (deal with user Break);
if ExceptionEvent then
③---> (deal with Device Exception);
④... ---> (deal with y axis go to ...?)
pdata^.x_axis:=pdata^.x_axis-1;
until pdata^.x_axis=0
end;

另外,吹牛谁不会,想看看 zjan521 老大如何写出这个 asm 代码。
 
我是来领分的
 
先报到,今天没时间了,明天再来仔细看看……:)
 
谢谢小雨哥,
谢谢各位大侠
 
我们算出脉冲数据发给37芯I/O口,数据定义如下:
37芯端口 输出端口 含义
11 IDO_0 电磁阀信号(DCF),输出高低电平
30 IDO_1 打印状态(PRT_ST),有一个输出
12 IDO_2 暂停(O_STOP)
31 IDO_3 OUT_1保留位
13 IDO_4 OUT_2保留位
32 IDO_5 方式选择(MOD_SEL)
14 IDO_6 打印力度PR1
33 IDO_7 打印力度PR2
15 IDO_8 X轴脉冲(X_CP)
34 IDO_9 X轴方向(X_CW)
16 IDO_10 XY_CLR
35 IDO_11 Y轴脉冲(Y_CP)
17 IDO_12 Y轴方向(Y_CW)
36 IDO_13 R轴脉冲(R_CP)
18 IDO_14 R轴方向(R_CW)
37 IDO_15 R_CLR
37芯端口 输入端口 含义
1 IDI_0 打印按钮(PRT_B)
20 IDI_1 暂停(IN_STOP)
2 IDI_2 电源检查(POW)
21 IDI_3 文件选择(F_SEL0)
3 IDI_4 文件选择(F_SEL1)
22 IDI_5 文件选择(F_SEL2)
4 IDI_6 文件选择(F_SEL3)
23 IDI_7 IN1_0保留位
5 IDI_8 X轴原点(X0)
24 IDI_9 Y轴原点(Y0)
6 IDI_10 R轴原点(R0)
25 IDI_11 IN1_1保留位
7 IDI_12 IN1_2保留位
26 IDI_13 IN2_0保留位
8 IDI_14 IN2_1保留位
27 IDI_15 IN2_2保留位
如何安位传出数据?
 
已经解决了吗?我是不是来晚了哦
 
to 小雨哥
我的意思是在操作模型简单并且频繁调用,对性能比较有影响,并且有优化可能的地方使用汇编
虽然我的汇编水平不高,但是合适的地方使用汇编进行优化还是可以做的。
我也不会在这个地方吹牛,那样没意思

[数据是X坐标Y坐标,都是16进制的数,比如x E505 Y FA02 。先转换成二进制的数,把这个数X存入一个16位寄存器中,再建一个16位累加器,低8位首先置1,然后把X左移一位得到的数X'与累加器的数相加,若溢出,则X-1,循环操作直到X=0为止。]
这样没有可能用汇编进行优化?而且我说的也是优化,而不是实现,因为当添加更多的逻辑在处理过程当中,问题越来越复杂的时候,使用汇编实现毫无疑义,但是对关乎性能的地方进行汇编优化还是有意义的

另外,我可算不上老大:) (这个称谓一般不是很推崇就是很不以为然,前者我还不够格,后者我也不甘心,呵呵)
 
TO:newsea008
你最新贴出的 38 芯电缆的问题,已经超出我的能力范围。恕我无能为力。有关按位
输出的问题,完全是基于设备的,很多设备本身使用状态字机制,在内部状态寄存器中填
入不同的操作标志,实现输出的控制。

另 TO:zjan521
当然不敢表示“不以为然”。看看满屏的回帖,除了你还多少在讨论问题,其它简直
扯淡!需要与你讨论的是:在问题还没有理出头绪前,你真有本事已经知道优化的关键了?
我不喜欢自己在别人帖子里说些离题的内容,假如说了,我会认真道歉。现在,我就准备好
向贴主道歉了,向你请教:假如你用 asm 写一个 HexToInt 函数,真的能保证比我用标准
Object Pascal 写的同样功能的函数快吗?如果可能,我另开帖子送 300 分,向你学习。
(补充一点,假如你的 asm 代码和我的 Object Pascal 一样快的话,应该算我赢。)
 
至少我可以嵌在函数体当中,而你的PAS版的至少要是一个函数调用,而且还有参数传递。
至于在函数内部的效率,我可以写出我认为效率最高的汇编代码(如果是内嵌的话,需要结合其它环境,否则环境和PAS的相同),而且像这样的小函数,传递的参数格式也可以有相对效率较好的声明(比如PChar和String),毕竟本来就没有几条指令. 但是效率和你的PAS的效率相比较,我不得而知,毕竟效率是有极限值的,但至少不会比你的PAS的效率差,呵呵,这样的比较我是立于不败之地的。:)
 
不一定。针对 function HexToInt(HexStr:string):integer 这样一个函数来讲,效率的
运用,将不是 Object Pascal 带来的,主要还是解题的应用。Object Pascal 只是形式上
的,论坛中多次出现这个函数的 Object Pascal 版本,没有一个逃脱计算这个模式。如果
这样,你就稳操胜券了,谁都知道 asm 的计算,是非常直接的,OP 最终还是要转换到 asm
去执行。如果 Object Pascal 版本超越了计算这个模式,而你的 asm 还在使用计算,胜
负是谁就很有得比了。—— 知道我为什么向你透露我的解题方向?虽然后果是可能我会输
给你,但要讨论的问题却会变得清晰,这就是,首先要有好的解题方法,才有更好的优化。
 
呵呵,小雨哥,有时候仅仅是讲道理是不够的,还是根据我常说的
“实践是检验真理的唯一标准”,来一个例子说明问题(见后)

很显然,小雨哥是想告诉我们这样一个事实(我拣个便宜[:D]):
给出一个题目:计算从 1 累加到 M 的结果。典型的程序员立刻就
写了一个 for 循环(对应我后面的 Calc1),发现效率不够,于是
zjan521 兄即对其进行汇编优化(对应后面的 Calc0),而小雨哥
则从容的用 ObjectPascal 写出了另一个版本(对应后面的 Calc2)

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
btn1: TButton;
btn2: TButton;
mmo1: TMemo;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

const
CalcMax = 100000;
CalcTimes = 1000;

type
TCalcFunc = function(Max: DWord): Integer;

// 这是我用汇编优化后的版本,没有考虑特殊情况,否则更慢
function Calc0(Max: DWord): Integer;
asm
mov ecx, eax
xor eax, eax
@loop:
add eax, ecx
dec ecx
jnz @loop
end;

// 典型解法
function Calc1(Max: DWord): Integer;
var
i: Integer;
begin
Result := 0;
for i := 1 to Max do
Result := Result + i;
end;

// 聪明的解法,根本不需要汇编优化,完全用纯 Pascal 写成
function Calc2(Max: DWord): Integer;
begin
Result := (1 + Max) * Max div 2;
end;

// 测试函数,让制定的计算方法多执行几次,以拉开时间差距
function TestCalc(CalcFunc: TCalcFunc
var Count: Integer): DWord;
var
i: Integer;
begin
Result := GetTickCount;

for i := 1 to CalcTimes do
Count := CalcFunc(CalcMax);

Result := GetTickCount - Result;
end;

// 输出测试结果
procedure TForm1.btn1Click(Sender: TObject);
var
Count: Integer;
begin
mmo1.Lines.Add(Format('Calc0 (%dms): %d.', [TestCalc(Calc0, Count), Count]));
mmo1.Lines.Add(Format('Calc1 (%dms): %d.', [TestCalc(Calc1, Count), Count]));
mmo1.Lines.Add(Format('Calc2 (%dms): %d.', [TestCalc(Calc2, Count), Count]));
end;

end.



最后结果如下:
Calc0 (451ms): 705082704. // 汇编优化
Calc1 (641ms): 705082704. // 典型解法
Calc2 (0ms): 705082704. // 聪明解法

很显然,也许本人功力不足,没有办法把 Calc0 优化的更快,就算 zjan521 兄
有能力将其速度再提高一倍(似乎不太可能),那也是 225ms,和 Calc2 的速度
还是没有办法相比。

道理应该很明显了,我就不多费“唇舌”了[:D]

 
呵呵,楼上两位说得都很对,可是我也没有错,我的观点就是优化,而不是直接用汇编解决问题。
写汇编之前不可能没有合适的算法和思路的。比较复杂的问题,PAS/C还可以先整体后局部,而汇编必须整体和局部通盘考虑.其实我觉得写汇编代码完全应该看作把其他语言的代码,至少是自然语言,翻译成汇编。也就是说其实汇编所能带来的好处就是更加直接,比如可以减少函数调用(在PAS里边没有inline),在处理地址,数据时更灵活一些,比如al ah这就是两个寄存器。从思路的角度上讲,C的思路其实和汇编已经非常相似了,
beta兄更是以实例说明了这个意思,可是如果解决这样的问题非要强迫我去在CALC0的基础上进行优化,呵呵,太不公平了。:)
 
顶部