واضح آرشیو وب فارسی:سایت ریسک: محاسبه Ln X - اسمبلی hamed 182001 06 خرداد 1388, 20:44سلام دوستان کسی برنامه ای داره که بشه ln x را تو اسمبلی حساب کرد. من میخوام فرمول R=Ln X- Ln y را حساب کنه. (تا 2 رقم اعشار) اگه کسی سورس برای محاسبه Ln داره برام بذاره ممنون میشم یا حداقل یکی راهنمایی کنه. the_king 07 خرداد 1388, 00:11سلام دوستان کسی برنامه ای داره که بشه ln x را تو اسمبلی حساب کرد. من میخوام فرمول R=Ln X- Ln y را حساب کنه. (تا 2 رقم اعشار) اگه کسی سورس برای محاسبه Ln داره برام بذاره ممنون میشم یا حداقل یکی راهنمایی کنه. اگه توضیحاتی که می نویسم براتون پیچیده است، شرمنده. تقصیر حقیر نیست، کار با کمک پردازنده ریاضی و محاسبه و نمایش اعشاری نیاز به مهارت در کار با پشته (Stack) هم داره که رعایت ترتیب هایش کمی پیچیده است. برای محاسبه Ln بایستی از Log2 (لگاریتم مبنای 2) کمک بگیریم، چون تنها مبنای لگاریتمی که کمک پردازنده های خانواده 8087 محاسبه می کنند، مبنای 2 است. دستور FYL2X لگاریتم مبنای 2 یک عدد را محاسبه می کند. شما کافیست که (Log2(x را بر (Log2(e تقسیم کنید تا (Ln(x بدست آید. برای محاسبه (Log2(e هم دستور FLDL2E وجود دارد. بایستی پیش از محاسبه توسط کمک پردازنده، آن عدد صحیح را توسط FILD به داخل پشته کمک پردازنده انتقال دهیم و پس از محاسبه مقدار نهایی آنرا توسط دستور FISTP به درون یک عدد صحیح برگردانیم. اما چون شما به دو رقم بعد از اعشار نیاز دارید، پیش از تبدیل به یک عدد صحیح، آنرا در 100 ضرب می کنیم. عدد در واقع صحیح است، اما دو رقم یکان و دهگان اش را جزو اعشار در نظر می گیریم. اگر X یک عدد صحیح دو بایتی (DW) و LNX100 هم یک حافظه دو بایتی دیگر برای ذخیره کردن Ln(x) * 100 باشد (ضربدر 100 کردیم تا دو رقم بعد از اعشار را از دست ندهیم)، کد زیر آنرا محاسبه خواهد کرد : FLD 1 FILD WORD PTR X FYL2X FLDL2E FDIV MOV WORD PTR LNX100, 100 FILD WORD PTR LNX100 FMUL FISTP WORD PTR LNX100 MOV AX, WORD PTR LNX100 برای چاپ عدد موجود در LNX100 بایستی یک روتین اختصاصی داشته باشیم. روتین print_ax یک عدد صحیح موجود در ax را روی صفحه نمایش نشان می دهد. روتین print_ax100 با استفاده از روتین print_ax می تواند یک عدد صحیح را که در 100 ضرب شده، بصورت اعشاری با دو رقم بعد از اعشار نمایش دهد. کد زیر توسط یک کامپایلر ML مایکروسافت قابل کامپایل شدن است و به عنوان مثال Ln(123 را محاسبه و نمایش می دهد (4.81) : .MODEL SMALL .DATA X DW 123 LNX100 DW ? .CODE .STARTUP FLD 1 FILD WORD PTR X FYL2X FLDL2E FDIV MOV WORD PTR LNX100, 100 FILD WORD PTR LNX100 FMUL FISTP WORD PTR LNX100 MOV AX, WORD PTR LNX100 CALL print_ax100 MOV AH, 8 INT 21h .EXIT 0 print_ax100: MOV BX, 100 XOR DX, DX DIV BX PUSH DX CALL print_ax POP AX OR AX, AX JZ print_finished PUSH AX MOV AH, 2 MOV DL, "." INT 21h POP AX OR AX, AX JGE is_positive1 NEG AX is_positive1: MOV BL, 10 DIV BL ADD AX, "00" PUSH AX MOV AH, 2 MOV DL, AL INT 21h POP DX CMP DH, "0" JE print_finished MOV DL, DH INT 21h print_finished: RET print_ax: OR AX, AX JGE is_positive2 PUSH AX MOV AH, 2 MOV DL, "-" INT 21h POP AX NEG AX is_positive2: MOV CX, 0 MOV BX, 10 get_digits: MOV DX, 0 DIV BX PUSH DX INC CX OR AX, AX JNE get_digits MOV AH, 2 print_digits: POP DX ADD DL, "0" INT 21h LOOP print_digits RET .STACK END کد برنامه asm به همراه فایل اجرایی exe ضمیمه این پست می باشد. hamed 182001 07 خرداد 1388, 12:13the_king عزیز خیلی ممنون از پست کاملتون. من خودم درس اسمبلی را خیلی وقت پیش داشتم. این برنامه را هم تا حدود زیادی فهمیدم. ولی مشکل اینجاست که من دارم یه پروژه دانشجویی خیلی در سطح پایین مینویسم برای یکی از دوستام. و نمیتونم ار این سطح دستورات استفاده کنم. اگه بتونی یکم سطح پایین تر راهنماییم کنی خیلی ممنون میشم. خودم دارم روی حلقه کار میکنم که با حلقه بنویسمش the_king 07 خرداد 1388, 13:03the_king عزیز خیلی ممنون از پست کاملتون. من خودم درس اسمبلی را خیلی وقت پیش داشتم. این برنامه را هم تا حدود زیادی فهمیدم. ولی مشکل اینجاست که من دارم یه پروژه دانشجویی خیلی در سطح پایین مینویسم برای یکی از دوستام. و نمیتونم ار این سطح دستورات استفاده کنم. اگه بتونی یکم سطح پایین تر راهنماییم کنی خیلی ممنون میشم. خودم دارم روی حلقه کار میکنم که با حلقه بنویسمش برای یک برنامه در سطح مبتدی موضوع خیلی سختی انتخاب کرده اید، چون محاسبه Ln نیازمند محاسبات اعشاریه که یا بایستی توسط کمک-پردازنده انجام شوند و یا خودتان روتین هایی برای ضرب و تقسیم و توان اعشاری ایجاد کنید که خودش کار را پیچیده می کند. مخصوصا محاسبه e ^ x پیچیده است، چون x یک عدد اعشاری است و با ضرب کردن پی در پی e در خودش قابل محاسبه نیست. اگر می خواهید با حلقه پیاده سازی اش کنید بایستی از متد تقریبی نیوتون استفاده کنید، فرض کنیم که x همان عددی باشد که می خواهیم (Ln(x را محاسبه کنیم : 1) ابتدا یک متغیر اعشاری a را برابر یک مقدار حدسی مثلا 1 قرار دهید. 2) مقدار اعشاری e (یعنی 2.71828182845905) را متغیر e قرار دهید. 3) مقدار نزدیک به صفر یک متغیر اعشاری epsilon را برای دقت محاسبه حلقه تعیین کنید، مثلا 0.0001 4) فرمول y = e ^ a را محاسبه کنید. بدیهی است که a اعشاری است و محاسبه کردن e به توان a خودش یک روتین پیچیده است. 5) از اختلاف مقدار میان y و x قدر مطلق گرفته و در متغیری نظیر d قرار دهید. (|d = |x - y) 6) اگر مقدار d کمتر از epsilon بود، پس ما (Ln(x را با تقریبی در حد epsilon محاسبه کرده ایم و می توانیم به مرحله آخر (مرحله 10) برویم. 7) مقدار جدید a را با فرمول (a = a - ((y - x) / y محاسبه می کنیم. 8) اگر مقدار a از عدد بزرگی مثل 200 بیشتر شد، آنرا به همان حد 200 تغییر می دهیم. 9) مجددا به مرحله 4 بر می گردیم و حلقه تکرار می شود. 10) مقدار a برابر (Ln(x بوده و با دقت epsilon محاسبه شده است. پیاده سازی این الگوریتم خیلی پیچیده تر از استفاده از دستورات کمک-پردازنده است، مخصوصا که بعد از نوشتن آن الگوریتم بایستی برای محاسبه e ^ a از سری های ریاضی کمک بگیرید : یک راه ساده تر هم این است که مقادیر e ^ 1 و e ^ 0.1 و e ^ 0.01 و ... رو قبلا در متغیر هایی ذخیره کرده و از فرمول زیر برای ضرب کردن پی در پی این متغیر ها در هم استفاده کنید : البته روتین های جمع و تفریق و ضرب و تقسیم اعشاری را به هر حال بایستی بسازید. hamed 182001 07 خرداد 1388, 13:43the_kibg عزیز ممنون خیلی کمک کردی
این صفحه را در گوگل محبوب کنید
[ارسال شده از: سایت ریسک]
[مشاهده در: www.ri3k.eu]
[تعداد بازديد از اين مطلب: 3879]