老刘 发表于 2019-4-22 15:23

[汇编][算法实战003]约瑟夫问题

据说著名犹太历史学家 Josephus 有过以下的故事:在罗马人占
领乔塔帕特后,39 个犹太人与 Josephus 及他的朋友躲到一个洞中,
39 个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方
式:41 个人围成一个圆圈,由第 1 个人开始报数,报数到第 3 个人,
该人就必须自杀,然后再由下一个重新报数,报数到的第 3 个人,该
人又自杀...直到所有人都自杀身亡为止,然而 Josephus 和他的朋友
并不想遵从。
一开始有 i 个人,数 j 去 1,最后剩余 k 个人。首先从一个人开
始,越过 j-1 个人,并杀掉第 j 个人;接着再越过 j-1 个人,并杀掉
第 j 个人...这个过程沿着圆圈一直进行,直到最终只剩下 k 个人,这
k 个人就可以继续活着。问题是,给定了 i、j、k 值,一开始要站在
什么地方才能避免被处决?聪明的Josephus要他的朋友先假装遵从,
他将朋友与自己安排在第 16 个与第 31 个位置,于是逃过了这场死亡
游戏。
;约瑟夫问题(一维数组) Algo
;Code By 老刘
;环境:MASM32 SDK
;编译指令:ml /coff 约瑟夫问题(一维数组).asm /link /subsystem:console
;参数:总人数、保留人数、每n个人杀一次的n(小于总人数)。
;参数最大值:999999。
;参考:MHL批处理标准教程之约瑟夫问题。


Include masm32rt.inc
Main Proto

.Data?
        bBuffer DB 999999 Dup (?)
        dwAll DD ?
        dwPersist DD ?
        bBuffer2 DB 11 Dup (?)
        dwCrLfZero DD ?
        dwJumpPlusOne DD ?
;End Data?

.Code
        Main Proc
                ;获得参数
                Invoke ArgClC,1,Offset bBuffer2
                Sub Esp,4
                Invoke atodw_ex,Offset bBuffer2
                Add Esp,4
                Mov dwAll,Eax
                Invoke ArgClC,2,Offset bBuffer2
                Sub Esp,4
                Invoke atodw_ex,Offset bBuffer2
                Add Esp,4
                Mov dwPersist,Eax
                Invoke ArgClC,3,Offset bBuffer2
                Sub Esp,4
                Invoke atodw_ex,Offset bBuffer2
                Add Esp,4
                Mov dwJumpPlusOne,Eax
               
                ;开始标记
                Lea Ebx,bBuffer
                Add Ebx,dwAll
                Mov Edx,dwAll
                Lea Esi,bBuffer
                Mov Edi,Esi
                Xor Eax,Eax
                .While Edx != dwPersist
                        Mov Ecx,dwJumpPlusOne
                        .Repeat
                                LodSB
                                Add Ecx,Eax
                                .If Esi == Ebx
                                        Mov Esi,Edi
                                .EndIf
                        .UntilCxZ
                        .If Esi == Edi
                                Mov Byte Ptr ,1
                        .Else
                                Dec Esi
                                Mov Byte Ptr ,1
                                Inc Esi
                        .EndIf
                        Dec Edx
                .EndW
               
                ;输出
                Mov dwCrLfZero,000D0AH
                Xor Ecx,Ecx
                Lea Esi,bBuffer
                Dec Esi
                .While Ecx != dwAll
                        Inc Ecx
                        .If Byte Ptr == 0
                                Pushad
                                Invoke dw2a,Ecx,Offset bBuffer2
                                Invoke StdOut,Offset bBuffer2
                                Invoke StdOut,Offset dwCrLfZero
                                Popad
                        .EndIf
                .EndW
               
                Ret
        Main EndP
       
        Start:
                Call Main
                Invoke ExitProcess,NULL
        End Start
End
;约瑟夫问题(单向循环链表) Algo
;Code By 老刘
;环境:MASM32 SDK
;编译指令:ml /coff 约瑟夫问题(单向循环链表).asm /link /subsystem:console
;参数:总人数、保留人数、每n个人杀一次的n(小于总人数)。
;参数最大值:1227。
;参考:MHL批处理标准教程之约瑟夫问题。


Include masm32rt.inc
Main Proto

OneWayLinkedList Struct
        Data DWord ?
        Next DWord ?
OneWayLinkedList EndS

.Data?
        dwAll DD ?
        dwPersist DD ?
        dwJump DD ?
        bBuffer2 DB 11 Dup (?)
        dwCrLfZero DD ?
        dwLinkedListHead DD ?
;End Data?

.Code
        Main Proc
                ;获得并处理参数
                Invoke ArgClC,1,Offset bBuffer2
                Sub Esp,4
                Invoke atodw_ex,Offset bBuffer2
                Add Esp,4
                Mov dwAll,Eax
                Invoke ArgClC,2,Offset bBuffer2
                Sub Esp,4
                Invoke atodw_ex,Offset bBuffer2
                Add Esp,4
                Mov dwPersist,Eax
                Invoke ArgClC,3,Offset bBuffer2
                Sub Esp,4
                Invoke atodw_ex,Offset bBuffer2
                Add Esp,4
                Dec Eax
                Mov dwJump,Eax
               
                ;创建链表
                Assume Ebx:Ptr OneWayLinkedList
                Assume Eax:Ptr OneWayLinkedList
                Invoke Alloc,SizeOf OneWayLinkedList
                Mov dwLinkedListHead,Eax
                Mov Ecx,dwAll
                Dec Ecx
                Xor Edx,Edx
                .Repeat
                        Mov Ebx,Eax
                        Inc Edx
                        Push Ecx
                        Push Edx
                        Invoke Alloc,SizeOf OneWayLinkedList
                        Pop Edx
                        Pop Ecx
                        Mov .Next,Eax
                        Mov .Data,Edx
                .UntilCxZ
                Mov Ebx,Eax
                Inc Edx
                Push dwLinkedListHead
                Pop .Next        ;指向链表结点1
                Mov .Data,Edx
                ;此时Ebx指向尾结点
               
                ;开始标记
                Mov Edx,dwAll
                .While Edx != dwPersist
                        Mov Ecx,dwJump
                        .If Ecx != 0
                                .Repeat
                                        Mov Ebx,.Next
                                .UntilCxZ
                        .EndIf
                        Mov Eax,.Next
                        Mov Ecx,.Next
                        Mov .Next,Ecx
                        Push Edx
                        Invoke Free,Eax
                        Pop Edx
                        Dec Edx
                .EndW
               
                ;遍历链表并输出
                Mov dwCrLfZero,000D0AH
                Mov Ecx,Ebx
                .Repeat
                        Pushad
                        Invoke dw2a,.Data,Offset bBuffer2
                        Invoke StdOut,Offset bBuffer2
                        Invoke StdOut,Offset dwCrLfZero
                        Popad
                        Mov Ebx,.Next
                .Until Ebx == Ecx
                Assume Ebx:Nothing
                Assume Eax:Nothing
               
                Ret
        Main EndP
       
        Start:
                Call Main
                Invoke ExitProcess,NULL
        End Start
End
同时欢迎大家回帖分享自己的代码!

老刘 发表于 2019-4-22 16:52

ayaoko 发表于 2019-4-22 16:15
请教一下楼主,汇编如何入门,和好的IDE

https://www.kanxue.com/book-section_list-31.htm
https://github.com/ThomasJaeger/VisualMASM

ayaoko 发表于 2019-4-22 16:15

请教一下楼主,汇编如何入门,和好的IDE

LeiSir 发表于 2019-4-22 19:39

太厉害了我cJAVAPython才都学了一点点阿
页: [1]
查看完整版本: [汇编][算法实战003]约瑟夫问题